home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / src / gdb-4.12 / gdb / m3-nat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-03  |  112.3 KB  |  4,559 lines

  1. /* Interface GDB to Mach 3.0 operating systems.
  2.    (Most) Mach 3.0 related routines live in this file.
  3.  
  4.    Copyright (C) 1992 Free Software Foundation, Inc.
  5.  
  6. This file is part of GDB.
  7.  
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12.  
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with this program; if not, write to the Free Software
  20. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  21.  
  22. /*
  23.  * Author: Jukka Virtanen <jtv@hut.fi>
  24.  *       Computing Centre
  25.  *         Helsinki University of Technology
  26.  *         Finland
  27.  *
  28.  * Thanks to my friends who helped with ideas and testing:
  29.  *
  30.  *    Johannes Helander, Antti Louko, Tero Mononen,
  31.  *    jvh@cs.hut.fi       alo@hut.fi   tmo@cs.hut.fi
  32.  *
  33.  *      Tero Kivinen       and          Eamonn McManus
  34.  *    kivinen@cs.hut.fi               emcmanus@gr.osf.org
  35.  *    
  36.  */
  37.  
  38. #include <stdio.h>
  39.  
  40. #include <mach.h>
  41. #include <servers/netname.h>
  42. #include <servers/machid.h>
  43. #include <mach/message.h>
  44. #include <mach/notify.h>
  45. #include <mach_error.h>
  46. #include <mach/exception.h>
  47. #include <mach/vm_attributes.h>
  48.  
  49. #include "defs.h"
  50. #include "inferior.h"
  51. #include "symtab.h"
  52. #include "value.h"
  53. #include "language.h"
  54. #include "target.h"
  55. #include "wait.h"
  56. #include "gdbcmd.h"
  57.  
  58. #include <servers/machid_lib.h>
  59.  
  60. /* Included only for signal names and NSIG
  61.  *
  62.  * note: There are many problems in signal handling with
  63.  *       gdb in Mach 3.0 in general.
  64.  */
  65. #include <signal.h>
  66. #define SIG_UNKNOWN 0    /* Exception that has no matching unix signal */
  67.  
  68. #include <cthreads.h>
  69.  
  70. /* This is what a cproc looks like.  This is here partly because
  71.    cthread_internals.h is not a header we can just #include, partly with
  72.    an eye towards perhaps getting this to work with cross-debugging
  73.    someday.  Best solution is if CMU publishes a real interface to this
  74.    stuff.  */
  75. #define CPROC_NEXT_OFFSET 0
  76. #define CPROC_NEXT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
  77. #define CPROC_INCARNATION_OFFSET (CPROC_NEXT_OFFSET + CPROC_NEXT_SIZE)
  78. #define CPROC_INCARNATION_SIZE (sizeof (cthread_t))
  79. #define CPROC_LIST_OFFSET (CPROC_INCARNATION_OFFSET + CPROC_INCARNATION_SIZE)
  80. #define CPROC_LIST_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
  81. #define CPROC_WAIT_OFFSET (CPROC_LIST_OFFSET + CPROC_LIST_SIZE)
  82. #define CPROC_WAIT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
  83. #define CPROC_REPLY_OFFSET (CPROC_WAIT_OFFSET + CPROC_WAIT_SIZE)
  84. #define CPROC_REPLY_SIZE (sizeof (mach_port_t))
  85. #define CPROC_CONTEXT_OFFSET (CPROC_REPLY_OFFSET + CPROC_REPLY_SIZE)
  86. #define CPROC_CONTEXT_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
  87. #define CPROC_LOCK_OFFSET (CPROC_CONTEXT_OFFSET + CPROC_CONTEXT_SIZE)
  88. #define CPROC_LOCK_SIZE (sizeof (spin_lock_t))
  89. #define CPROC_STATE_OFFSET (CPROC_LOCK_OFFSET + CPROC_LOCK_SIZE)
  90. #define CPROC_STATE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
  91. #define CPROC_WIRED_OFFSET (CPROC_STATE_OFFSET + CPROC_STATE_SIZE)
  92. #define CPROC_WIRED_SIZE (sizeof (mach_port_t))
  93. #define CPROC_BUSY_OFFSET (CPROC_WIRED_OFFSET + CPROC_WIRED_SIZE)
  94. #define CPROC_BUSY_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
  95. #define CPROC_MSG_OFFSET (CPROC_BUSY_OFFSET + CPROC_BUSY_SIZE)
  96. #define CPROC_MSG_SIZE (sizeof (mach_msg_header_t))
  97. #define CPROC_BASE_OFFSET (CPROC_MSG_OFFSET + CPROC_MSG_SIZE)
  98. #define CPROC_BASE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
  99. #define CPROC_SIZE_OFFSET (CPROC_BASE_OFFSET + CPROC_BASE_SIZE)
  100. #define CPROC_SIZE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
  101. #define CPROC_SIZE (CPROC_SIZE_OFFSET + CPROC_SIZE_SIZE)
  102.  
  103. /* Values for the state field in the cproc.  */
  104. #define CPROC_RUNNING    0
  105. #define CPROC_SWITCHING 1
  106. #define CPROC_BLOCKED    2
  107. #define CPROC_CONDWAIT    4
  108.  
  109. /* For cproc and kernel thread mapping */
  110. typedef struct gdb_thread {
  111.   mach_port_t    name;
  112.   CORE_ADDR    sp;
  113.   CORE_ADDR    pc;
  114.   CORE_ADDR    fp;
  115.   boolean_t     in_emulator;
  116.   int        slotid;
  117.  
  118.   /* This is for the mthreads list.  It points to the cproc list.
  119.      Perhaps the two lists should be merged (or perhaps it was a mistake
  120.      to make them both use a struct gdb_thread).  */
  121.   struct gdb_thread *cproc;
  122.  
  123.   /* These are for the cproc list, which is linked through the next field
  124.      of the struct gdb_thread.  */
  125.   char raw_cproc[CPROC_SIZE];
  126.   /* The cthread which is pointed to by the incarnation field from the
  127.      cproc.  This points to the copy we've read into GDB.  */
  128.   cthread_t cthread;
  129.   /* Point back to the mthreads list.  */
  130.   int reverse_map;
  131.   struct gdb_thread *next;
  132. } *gdb_thread_t;
  133.  
  134. /* 
  135.  * Actions for Mach exceptions.
  136.  *
  137.  * sigmap field maps the exception to corresponding Unix signal.
  138.  *
  139.  * I do not know how to map the exception to unix signal
  140.  * if SIG_UNKNOWN is specified.
  141.  */
  142.  
  143. struct exception_list {
  144.   char *name;
  145.   boolean_t forward;
  146.   boolean_t print;
  147.   int       sigmap;
  148. } exception_map[] = {
  149.   {"not_mach3_exception",    FALSE, TRUE,  SIG_UNKNOWN},
  150.   {"EXC_BAD_ACCESS",        FALSE, TRUE,  SIGSEGV},
  151.   {"EXC_BAD_INSTRUCTION",    FALSE, TRUE,  SIGILL},
  152.   {"EXC_ARITHMETIC",        FALSE, TRUE,  SIGFPE},
  153.   {"EXC_EMULATION",        FALSE, TRUE,  SIGEMT},    /* ??? */
  154.   {"EXC_SOFTWARE",        FALSE, TRUE,  SIG_UNKNOWN},
  155.   {"EXC_BREAKPOINT",        FALSE, FALSE, SIGTRAP}
  156. };
  157.  
  158. /* Mach exception table size */
  159. int max_exception = sizeof(exception_map)/sizeof(struct exception_list) - 1;
  160.  
  161. #define MAX_EXCEPTION max_exception
  162.  
  163. WAITTYPE wait_status;
  164.  
  165. /* If you define this, intercepted bsd server calls will be
  166.  * dumped while waiting the inferior to EXEC the correct
  167.  * program
  168.  */
  169. /* #define DUMP_SYSCALL        /* debugging interceptor */
  170.  
  171. /* xx_debug() outputs messages if this is nonzero.
  172.  * If > 1, DUMP_SYSCALL will dump message contents.
  173.  */
  174. int debug_level = 0;
  175.  
  176. /* "Temporary" debug stuff */
  177. void
  178. xx_debug (fmt, a,b,c)
  179. char *fmt;
  180. int a,b,c;
  181. {
  182.   if (debug_level)
  183.     warning (fmt, a, b, c);
  184. }
  185.  
  186. /* This is in libmach.a */
  187. extern  mach_port_t  name_server_port;
  188.  
  189. /* Set in catch_exception_raise */
  190. int stop_exception, stop_code, stop_subcode;
  191. int stopped_in_exception;
  192.  
  193. /* Thread that was the active thread when we stopped */
  194. thread_t stop_thread = MACH_PORT_NULL;
  195.  
  196. char *hostname = "";
  197.  
  198. /* Set when task is attached or created */
  199. boolean_t emulator_present = FALSE;
  200.  
  201. task_t   inferior_task;
  202. thread_t current_thread;
  203.  
  204. /* Exception ports for inferior task */
  205. mach_port_t inferior_exception_port     = MACH_PORT_NULL;
  206. mach_port_t inferior_old_exception_port = MACH_PORT_NULL;
  207.  
  208. /* task exceptions and notifications */
  209. mach_port_t inferior_wait_port_set    = MACH_PORT_NULL;
  210. mach_port_t our_notify_port           = MACH_PORT_NULL;
  211.  
  212. /* This is "inferior_wait_port_set" when not single stepping, and
  213.  *         "singlestepped_thread_port" when we are single stepping.
  214.  * 
  215.  * This is protected by a cleanup function: discard_single_step()
  216.  */
  217. mach_port_t currently_waiting_for    = MACH_PORT_NULL;
  218.  
  219. /* A port for external messages to gdb.
  220.  * External in the meaning that they do not come
  221.  * from the inferior_task, but rather from external
  222.  * tasks.
  223.  *
  224.  * As a debugging feature:
  225.  * A debugger debugging another debugger can stop the
  226.  * inferior debugger by the following command sequence
  227.  * (without running external programs)
  228.  *
  229.  *    (top-gdb) set stop_inferior_gdb ()
  230.  *    (top-gdb) continue
  231.  */
  232. mach_port_t our_message_port           = MACH_PORT_NULL;
  233.  
  234. /* For single stepping */
  235. mach_port_t thread_exception_port     = MACH_PORT_NULL;
  236. mach_port_t thread_saved_exception_port = MACH_PORT_NULL;
  237. mach_port_t singlestepped_thread_port   = MACH_PORT_NULL;
  238.  
  239. /* For machid calls */
  240. mach_port_t mid_server = MACH_PORT_NULL;
  241. mach_port_t mid_auth   = MACH_PORT_NULL;
  242.  
  243. /* If gdb thinks the inferior task is not suspended, it
  244.  * must take suspend/abort the threads when it reads the state.
  245.  */
  246. int must_suspend_thread = 0;
  247.  
  248. /* When single stepping, we switch the port that mach_really_wait() listens to.
  249.  * This cleanup is a guard to prevent the port set from being left to
  250.  * the singlestepped_thread_port when error() is called.
  251.  *  This is nonzero only when we are single stepping.
  252.  */
  253. #define NULL_CLEANUP (struct cleanup *)0
  254. struct cleanup *cleanup_step = NULL_CLEANUP;
  255.  
  256.  
  257. #if 0
  258. #define MACH_TYPE_EXCEPTION_PORT    -1
  259. #endif
  260.  
  261. /* Chain of ports to remember requested notifications. */
  262.  
  263. struct port_chain {
  264.   struct port_chain *next;
  265.   mach_port_t         port;
  266.   int             type;
  267.   int             mid;  /* Now only valid with MACH_TYPE_THREAD and */
  268.                  /*  MACH_TYPE_THREAD */
  269. };
  270. typedef struct port_chain *port_chain_t;
  271.  
  272. /* Room for chain nodes comes from pchain_obstack */
  273. struct obstack pchain_obstack;
  274. struct obstack *port_chain_obstack = &pchain_obstack;
  275.  
  276. /* For thread handling */
  277. struct obstack Cproc_obstack;
  278. struct obstack *cproc_obstack = &Cproc_obstack;
  279.  
  280. /* the list of notified ports */
  281. port_chain_t notify_chain = (port_chain_t) NULL;
  282.  
  283. port_chain_t
  284. port_chain_insert (list, name, type)
  285.      port_chain_t list;
  286.      mach_port_t name;
  287.      int     type;
  288. {
  289.   kern_return_t ret;
  290.   port_chain_t new;
  291.   int mid;
  292.  
  293.   if (! MACH_PORT_VALID (name))
  294.     return list;
  295.   
  296.   if (type == MACH_TYPE_TASK || type == MACH_TYPE_THREAD)
  297.     {
  298.       if (! MACH_PORT_VALID (mid_server))
  299.     {
  300.       warning ("Machid server port invalid, can not map port 0x%x to MID",
  301.            name);
  302.       mid = name;
  303.     }
  304.       else
  305.     {
  306.       ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
  307.       
  308.       if (ret != KERN_SUCCESS)
  309.         {
  310.           warning ("Can not map name (0x%x) to MID with machid", name);
  311.           mid = name;
  312.         }
  313.     }
  314.     }
  315.   else
  316.     mid = 3735928559;    /* 0x? :-) */
  317.  
  318.   new = (port_chain_t) obstack_alloc (port_chain_obstack,
  319.                       sizeof (struct port_chain));
  320.   new->next  = list;
  321.   new->port  = name;
  322.   new->type  = type;
  323.   new->mid   = mid;
  324.  
  325.   return new;
  326. }
  327.  
  328. port_chain_t
  329. port_chain_delete (list, elem)
  330.      port_chain_t list;
  331.      mach_port_t elem;
  332. {
  333.   if (list)
  334.     if (list->port == elem)
  335.       list = list->next;
  336.     else
  337.       while (list->next)
  338.     {
  339.       if (list->next->port == elem)
  340.         list->next = list->next->next; /* GCd with obstack_free() */
  341.       else
  342.         list = list->next;
  343.     }
  344.   return list;
  345. }
  346.  
  347. void
  348. port_chain_destroy (ostack)
  349.      struct obstack *ostack;
  350. {
  351.   obstack_free (ostack, 0);
  352.   obstack_init (ostack);
  353. }
  354.  
  355. port_chain_t
  356. port_chain_member (list, elem)
  357.      port_chain_t list;
  358.      mach_port_t elem;
  359. {
  360.   while (list)
  361.     {
  362.       if (list->port == elem)
  363.     return list;
  364.       list = list->next;
  365.     }
  366.   return (port_chain_t) NULL;
  367. }
  368.  
  369. int
  370. map_port_name_to_mid (name, type)
  371. mach_port_t name;
  372. int         type;
  373. {
  374.   port_chain_t elem;
  375.  
  376.   if (!MACH_PORT_VALID (name))
  377.     return -1;
  378.  
  379.   elem = port_chain_member (notify_chain, name);
  380.  
  381.   if (elem && (elem->type == type))
  382.     return elem->mid;
  383.   
  384.   if (elem)
  385.     return -1;
  386.   
  387.   if (! MACH_PORT_VALID (mid_server))
  388.     {
  389.       warning ("Machid server port invalid, can not map port 0x%x to mid",
  390.            name);
  391.       return -1;
  392.     }
  393.   else
  394.     {
  395.       int mid;
  396.       kern_return_t ret;
  397.  
  398.       ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
  399.       
  400.       if (ret != KERN_SUCCESS)
  401.     {
  402.       warning ("Can not map name (0x%x) to mid with machid", name);
  403.       return -1;
  404.     }
  405.       return mid;
  406.     }
  407. }
  408.  
  409. /* Guard for currently_waiting_for and singlestepped_thread_port */
  410. static void
  411. discard_single_step (thread)
  412.      thread_t thread;
  413. {
  414.   currently_waiting_for = inferior_wait_port_set;
  415.  
  416.   cleanup_step = NULL_CLEANUP;
  417.   if (MACH_PORT_VALID (thread) && MACH_PORT_VALID (singlestepped_thread_port))
  418.     setup_single_step (thread, FALSE);
  419. }
  420.  
  421. setup_single_step (thread, start_step)
  422.      thread_t  thread;
  423.      boolean_t start_step;
  424. {
  425.   kern_return_t ret;
  426.  
  427.   if (! MACH_PORT_VALID (thread))
  428.     error ("Invalid thread supplied to setup_single_step");
  429.   else
  430.     {
  431.       mach_port_t teport;
  432.  
  433.       /* Get the current thread exception port */
  434.       ret = thread_get_exception_port (thread, &teport);
  435.       CHK ("Getting thread's exception port", ret);
  436.       
  437.       if (start_step)
  438.     {
  439.       if (MACH_PORT_VALID (singlestepped_thread_port))
  440.         {
  441.           warning ("Singlestepped_thread_port (0x%x) is still valid?",
  442.                singlestepped_thread_port);
  443.           singlestepped_thread_port = MACH_PORT_NULL;
  444.         }
  445.       
  446.       /* If we are already stepping this thread */
  447.       if (MACH_PORT_VALID (teport) && teport == thread_exception_port)
  448.         {
  449.           ret = mach_port_deallocate (mach_task_self (), teport);
  450.           CHK ("Could not deallocate thread exception port", ret);
  451.         }
  452.       else
  453.         {
  454.           ret = thread_set_exception_port (thread, thread_exception_port);
  455.           CHK ("Setting exception port for thread", ret);
  456. #if 0
  457.           /* Insert thread exception port to wait port set */
  458.           ret = mach_port_move_member (mach_task_self(), 
  459.                        thread_exception_port,
  460.                        inferior_wait_port_set);
  461.           CHK ("Moving thread exception port to inferior_wait_port_set",
  462.            ret);
  463. #endif
  464.           thread_saved_exception_port = teport;
  465.         }
  466.       
  467.       thread_trace (thread, TRUE);
  468.       
  469.       singlestepped_thread_port   = thread_exception_port;
  470.       currently_waiting_for       = singlestepped_thread_port;
  471.       cleanup_step = make_cleanup (discard_single_step, thread);
  472.     }
  473.       else
  474.     {
  475.       if (! MACH_PORT_VALID (teport))
  476.         error ("Single stepped thread had an invalid exception port?");
  477.  
  478.       if (teport != thread_exception_port)
  479.         error ("Single stepped thread had an unknown exception port?");
  480.       
  481.       ret = mach_port_deallocate (mach_task_self (), teport);
  482.       CHK ("Couldn't deallocate thread exception port", ret);
  483. #if 0
  484.       /* Remove thread exception port from wait port set */
  485.       ret = mach_port_move_member (mach_task_self(), 
  486.                        thread_exception_port,
  487.                        MACH_PORT_NULL);
  488.       CHK ("Removing thread exception port from inferior_wait_port_set",
  489.            ret);
  490. #endif      
  491.       /* Restore thread's old exception port */
  492.       ret = thread_set_exception_port (thread,
  493.                        thread_saved_exception_port);
  494.       CHK ("Restoring stepped thread's exception port", ret);
  495.       
  496.       if (MACH_PORT_VALID (thread_saved_exception_port))
  497.         (void) mach_port_deallocate (mach_task_self (),
  498.                      thread_saved_exception_port);
  499.       
  500.       thread_trace (thread, FALSE);
  501.       
  502.       singlestepped_thread_port = MACH_PORT_NULL;
  503.       currently_waiting_for = inferior_wait_port_set;
  504.       if (cleanup_step)
  505.         discard_cleanups (cleanup_step);
  506.     }
  507.     }
  508. }
  509.  
  510. static
  511. request_notify (name, variant, type)
  512.      mach_port_t    name;
  513.      mach_msg_id_t    variant;
  514.      int            type;
  515. {
  516.   kern_return_t ret;
  517.   mach_port_t    previous_port_dummy = MACH_PORT_NULL;
  518.   
  519.   if (! MACH_PORT_VALID (name))
  520.     return;
  521.   
  522.   if (port_chain_member (notify_chain, name))
  523.     return;
  524.  
  525.   ret = mach_port_request_notification (mach_task_self(),
  526.                     name,
  527.                     variant,
  528.                     1,
  529.                     our_notify_port,
  530.                     MACH_MSG_TYPE_MAKE_SEND_ONCE,
  531.                     &previous_port_dummy);
  532.   CHK ("Serious: request_notify failed", ret);
  533.  
  534.   (void) mach_port_deallocate (mach_task_self (),
  535.                    previous_port_dummy);
  536.  
  537.   notify_chain = port_chain_insert (notify_chain, name, type);
  538. }
  539.  
  540. reverse_msg_bits(msgp, type)
  541.      mach_msg_header_t    *msgp;
  542.      int type;
  543. {
  544.   int        rbits,lbits;
  545.   rbits = MACH_MSGH_BITS_REMOTE(msgp->msgh_bits);
  546.   lbits = type;
  547.   msgp->msgh_bits =
  548.     (msgp->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
  549.       MACH_MSGH_BITS(lbits,rbits);
  550. }
  551.  
  552. /* On the third day He said:
  553.  
  554.        Let this be global
  555.     and then it was global.
  556.  
  557.    When creating the inferior fork, the
  558.    child code in inflow.c sets the name of the
  559.    bootstrap_port in its address space to this
  560.    variable.
  561.  
  562.    The name is transferred to our address space
  563.    with mach3_read_inferior().
  564.  
  565.    Thou shalt not do this with
  566.    task_get_bootstrap_port() in this task, since
  567.    the name in the inferior task is different than
  568.    the one we get.
  569.  
  570.    For blessed are the meek, as they shall inherit
  571.    the address space.
  572.  */
  573. mach_port_t original_server_port_name = MACH_PORT_NULL;
  574.  
  575.  
  576. /* Called from inferior after FORK but before EXEC */
  577. static void
  578. m3_trace_me ()
  579. {
  580.   kern_return_t ret;
  581.   
  582.   /* Get the NAME of the bootstrap port in this task
  583.      so that GDB can read it */
  584.   ret = task_get_bootstrap_port (mach_task_self (),
  585.                  &original_server_port_name);
  586.   if (ret != KERN_SUCCESS)
  587.     abort ();
  588.   ret = mach_port_deallocate (mach_task_self (),
  589.                   original_server_port_name);
  590.   if (ret != KERN_SUCCESS)
  591.     abort ();
  592.   
  593.   /* Suspend this task to let the parent change my ports.
  594.      Resumed by the debugger */
  595.   ret = task_suspend (mach_task_self ());
  596.   if (ret != KERN_SUCCESS)
  597.     abort ();
  598. }
  599.  
  600. /*
  601.  * Intercept system calls to Unix server.
  602.  * After EXEC_COUNTER calls to exec(), return.
  603.  *
  604.  * Pre-assertion:  Child is suspended. (Not verified)
  605.  * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
  606.  */
  607.  
  608. void
  609. intercept_exec_calls (exec_counter)
  610.      int exec_counter;
  611. {
  612.   struct syscall_msg_t {
  613.     mach_msg_header_t    header;
  614.     mach_msg_type_t     type;
  615.     char room[ 2000 ];    /* Enuff space */
  616.   };
  617.  
  618.   struct syscall_msg_t syscall_in, syscall_out;
  619.  
  620.   mach_port_t fake_server;
  621.   mach_port_t original_server_send;
  622.   mach_port_t original_exec_reply;
  623.   mach_port_t exec_reply;
  624.   mach_port_t exec_reply_send;
  625.   mach_msg_type_name_t acquired;
  626.   mach_port_t emulator_server_port_name;
  627.   struct task_basic_info info;
  628.   mach_msg_type_number_t info_count;
  629.  
  630.   kern_return_t ret;
  631.  
  632.   if (exec_counter <= 0)
  633.     return;        /* We are already set up in the correct program */
  634.  
  635.   ret = mach_port_allocate(mach_task_self(), 
  636.                MACH_PORT_RIGHT_RECEIVE,
  637.                &fake_server);
  638.   CHK("create inferior_fake_server port failed", ret);
  639.   
  640.   /* Wait for inferior_task to suspend itself */
  641.   while(1)
  642.     {
  643.       info_count = sizeof (info);
  644.       ret = task_info (inferior_task,
  645.                TASK_BASIC_INFO,
  646.                (task_info_t)&info,
  647.                &info_count);
  648.       CHK ("Task info", ret);
  649.  
  650.       if (info.suspend_count)
  651.     break;
  652.  
  653.       /* Note that the definition of the parameter was undefined
  654.        * at the time of this writing, so I just use an `ad hoc' value.
  655.        */
  656.       (void) swtch_pri (42); /* Universal Priority Value */
  657.     }
  658.  
  659.   /* Read the inferior's bootstrap port name */
  660.   if (!mach3_read_inferior (&original_server_port_name,
  661.                 &original_server_port_name,
  662.                 sizeof (original_server_port_name)))
  663.     error ("Can't read inferior task bootstrap port name");
  664.  
  665.   /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
  666.   /*      Should get refs, and set them back when restoring */
  667.   /* Steal the original bsd server send right from inferior */
  668.   ret = mach_port_extract_right (inferior_task,
  669.                  original_server_port_name,
  670.                  MACH_MSG_TYPE_MOVE_SEND,
  671.                  &original_server_send,
  672.                  &acquired);
  673.   CHK("mach_port_extract_right (bsd server send)",ret);
  674.   
  675.   if (acquired != MACH_MSG_TYPE_PORT_SEND)
  676.     error("Incorrect right extracted, send right to bsd server excpected");
  677.  
  678.   ret = mach_port_insert_right (inferior_task,
  679.                 original_server_port_name,
  680.                 fake_server,
  681.                 MACH_MSG_TYPE_MAKE_SEND);
  682.   CHK("mach_port_insert_right (fake server send)",ret);
  683.  
  684.   xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
  685.         fake_server,
  686.         original_server_port_name, original_server_send);
  687.  
  688.   /* A receive right to the reply generated by unix server exec() request */
  689.   ret = mach_port_allocate(mach_task_self(), 
  690.                MACH_PORT_RIGHT_RECEIVE,
  691.                &exec_reply);
  692.   CHK("create intercepted_reply_port port failed", ret);
  693.     
  694.   /* Pass this send right to Unix server so it replies to us after exec() */
  695.   ret = mach_port_extract_right (mach_task_self (),
  696.                  exec_reply,
  697.                  MACH_MSG_TYPE_MAKE_SEND_ONCE,
  698.                  &exec_reply_send,
  699.                  &acquired);
  700.   CHK("mach_port_extract_right (exec_reply)",ret);
  701.  
  702.   if (acquired != MACH_MSG_TYPE_PORT_SEND_ONCE)
  703.     error("Incorrect right extracted, send once excpected for exec reply");
  704.  
  705.   ret = mach_port_move_member(mach_task_self(), 
  706.                   fake_server,
  707.                   inferior_wait_port_set);
  708.   CHK ("Moving fake syscall port to inferior_wait_port_set", ret);
  709.  
  710.   xx_debug ("syscall fake server set up, resuming inferior\n");
  711.   
  712.   ret = task_resume (inferior_task);
  713.   CHK("task_resume (startup)", ret);
  714.     
  715.   /* Read requests from the inferior.
  716.      Pass directly through everything else except exec() calls.
  717.    */
  718.   while(exec_counter > 0)
  719.     {
  720.       ret = mach_msg (&syscall_in.header,    /* header */
  721.               MACH_RCV_MSG,        /* options */
  722.               0,            /* send size */
  723.               sizeof (struct syscall_msg_t), /* receive size */
  724.               inferior_wait_port_set,        /* receive_name */
  725.               MACH_MSG_TIMEOUT_NONE,
  726.               MACH_PORT_NULL);
  727.       CHK("mach_msg (intercepted sycall)", ret);
  728.         
  729. #ifdef DUMP_SYSCALL
  730.       print_msg (&syscall_in.header);
  731. #endif
  732.  
  733.       /* ASSERT : msgh_local_port == fake_server */
  734.  
  735.       if (notify_server (&syscall_in.header, &syscall_out.header))
  736.     error ("received a notify while intercepting syscalls");
  737.  
  738.       if (syscall_in.header.msgh_id == MIG_EXEC_SYSCALL_ID)
  739.     {
  740.       xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter);
  741.       if (exec_counter == 1)
  742.         {
  743.           original_exec_reply = syscall_in.header.msgh_remote_port;
  744.           syscall_in.header.msgh_remote_port = exec_reply_send;
  745.         }
  746.       exec_counter--;
  747.     }
  748.         
  749.       syscall_in.header.msgh_local_port  = syscall_in.header.msgh_remote_port;
  750.       syscall_in.header.msgh_remote_port = original_server_send;
  751.  
  752.       reverse_msg_bits(&syscall_in.header, MACH_MSG_TYPE_COPY_SEND);
  753.  
  754.       ret = mach_msg_send (&syscall_in.header);
  755.       CHK ("Forwarded syscall", ret);
  756.     }
  757.     
  758.   ret = mach_port_move_member(mach_task_self(), 
  759.                   fake_server,
  760.                   MACH_PORT_NULL);
  761.   CHK ("Moving fake syscall out of inferior_wait_port_set", ret);
  762.  
  763.   ret = mach_port_move_member(mach_task_self(), 
  764.                   exec_reply,
  765.                   inferior_wait_port_set);
  766.   CHK ("Moving exec_reply to inferior_wait_port_set", ret);
  767.  
  768.   ret = mach_msg (&syscall_in.header,    /* header */
  769.           MACH_RCV_MSG,        /* options */
  770.           0,            /* send size */
  771.           sizeof (struct syscall_msg_t),    /* receive size */
  772.           inferior_wait_port_set,        /* receive_name */
  773.           MACH_MSG_TIMEOUT_NONE,
  774.           MACH_PORT_NULL);
  775.   CHK("mach_msg (exec reply)", ret);
  776.  
  777.   ret = task_suspend (inferior_task);
  778.   CHK ("Suspending inferior after last exec", ret);
  779.  
  780.   must_suspend_thread = 0;
  781.  
  782.   xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
  783.  
  784. #ifdef DUMP_SYSCALL
  785.       print_msg (&syscall_in.header);
  786. #endif
  787.  
  788.   /* Message should appear as if it came from the unix server */
  789.   syscall_in.header.msgh_local_port = MACH_PORT_NULL;
  790.  
  791.   /*  and go to the inferior task original reply port */
  792.   syscall_in.header.msgh_remote_port = original_exec_reply;
  793.  
  794.   reverse_msg_bits(&syscall_in.header, MACH_MSG_TYPE_MOVE_SEND_ONCE);
  795.  
  796.   ret = mach_msg_send (&syscall_in.header);
  797.   CHK ("Forwarding exec reply to inferior", ret);
  798.  
  799.   /* Garbage collect */
  800.   ret = mach_port_deallocate (inferior_task,
  801.                   original_server_port_name);
  802.   CHK ("deallocating fake server send right", ret);
  803.  
  804.   ret = mach_port_insert_right (inferior_task,
  805.                 original_server_port_name,
  806.                 original_server_send,
  807.                 MACH_MSG_TYPE_MOVE_SEND);
  808.   CHK ("Restoring the original bsd server send right", ret);
  809.  
  810.   ret = mach_port_destroy (mach_task_self (),
  811.                fake_server);
  812.   fake_server = MACH_PORT_DEAD;
  813.   CHK("mach_port_destroy (fake_server)", ret);
  814.  
  815.   ret = mach_port_destroy (mach_task_self (),
  816.                exec_reply);
  817.   exec_reply = MACH_PORT_DEAD;
  818.   CHK("mach_port_destroy (exec_reply)", ret);
  819.  
  820.   xx_debug ("Done with exec call interception\n");
  821. }
  822.  
  823. void
  824. consume_send_rights (thread_list, thread_count)
  825.      thread_array_t thread_list;
  826.      int            thread_count;
  827. {
  828.   int index;
  829.  
  830.   if (!thread_count)
  831.     return;
  832.  
  833.   for (index = 0; index < thread_count; index++)
  834.     {
  835.       /* Since thread kill command kills threads, don't check ret */
  836.       (void) mach_port_deallocate (mach_task_self (),
  837.                    thread_list [ index ]);
  838.     }
  839. }
  840.  
  841. /* suspend/abort/resume a thread. */
  842. setup_thread (thread, what)
  843.      mach_port_t thread;
  844.      int what;
  845. {
  846.   kern_return_t ret;
  847.  
  848.   if (what)
  849.     {
  850.       ret = thread_suspend (thread);
  851.       CHK ("setup_thread thread_suspend", ret);
  852.       
  853.       ret = thread_abort (thread);
  854.       CHK ("setup_thread thread_abort", ret);
  855.     }
  856.   else
  857.     {
  858.       ret = thread_resume (thread);
  859.       CHK ("setup_thread thread_resume", ret);
  860.     }
  861. }
  862.  
  863. int
  864. map_slot_to_mid (slot, threads, thread_count)
  865.      int slot;
  866.      thread_array_t threads;
  867.      int thread_count;
  868. {
  869.   kern_return_t ret;
  870.   int deallocate = 0;
  871.   int index;
  872.   int mid;
  873.  
  874.   if (! threads)
  875.     {
  876.       deallocate++;
  877.       ret = task_threads (inferior_task, &threads, &thread_count);
  878.       CHK ("Can not select a thread from a dead task", ret);
  879.     }
  880.   
  881.   if (slot < 0 || slot >= thread_count)
  882.     {
  883.       if (deallocate)
  884.     {
  885.       consume_send_rights (threads, thread_count);
  886.       (void) vm_deallocate (mach_task_self(), (vm_address_t)threads, 
  887.                 (thread_count * sizeof(mach_port_t)));
  888.     }
  889.       if (slot < 0)
  890.     error ("invalid slot number");
  891.       else
  892.     return -(slot+1);
  893.     }
  894.  
  895.   mid = map_port_name_to_mid (threads [slot], MACH_TYPE_THREAD);
  896.  
  897.   if (deallocate)
  898.     {
  899.       consume_send_rights (threads, thread_count);
  900.       (void) vm_deallocate (mach_task_self(), (vm_address_t)threads, 
  901.                 (thread_count * sizeof(mach_port_t)));
  902.     }
  903.  
  904.   return mid;
  905. }
  906.  
  907. static int
  908. parse_thread_id (arg, thread_count, slots)
  909.      char *arg;
  910.      int thread_count;
  911.      int slots;
  912. {
  913.   kern_return_t ret;
  914.   int mid;
  915.   int slot;
  916.   int index;
  917.   
  918.   if (arg == 0)
  919.     return 0;
  920.   
  921.   while (*arg && (*arg == ' ' || *arg == '\t'))
  922.     arg++;
  923.   
  924.   if (! *arg)
  925.     return 0;
  926.   
  927.   /* Currently parse MID and @SLOTNUMBER */
  928.   if (*arg != '@')
  929.     {
  930.       mid = atoi (arg);
  931.       if (mid <= 0)
  932.     error ("valid thread mid expected");
  933.       return mid;
  934.     }
  935.   
  936.   arg++;
  937.   slot = atoi (arg);
  938.  
  939.   if (slot < 0)
  940.     error ("invalid slot number");
  941.  
  942.   /* If you want slot numbers to remain slot numbers, set slots.
  943.    *
  944.    * Well, since 0 is reserved, return the ordinal number
  945.    * of the thread rather than the slot number. Awk, this
  946.    * counts as a kludge.
  947.    */
  948.   if (slots)
  949.     return -(slot+1);
  950.  
  951.   if (thread_count && slot >= thread_count)
  952.     return -(slot+1);
  953.  
  954.   mid = map_slot_to_mid (slot);
  955.   
  956.   return mid;
  957. }
  958.  
  959. /* THREAD_ID 0 is special; it selects the first kernel
  960.  * thread from the list (i.e. SLOTNUMBER 0)
  961.  * This is used when starting the program with 'run' or when attaching.
  962.  *
  963.  * If FLAG is 0 the context is not changed, and the registers, frame, etc
  964.  * will continue to describe the old thread.
  965.  *
  966.  * If FLAG is nonzero, really select the thread.
  967.  * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
  968.  * 
  969.  */
  970. kern_return_t
  971. select_thread (task, thread_id, flag)
  972.      mach_port_t task;
  973.      int thread_id;
  974.      int flag;
  975. {
  976.   thread_array_t thread_list;
  977.   int thread_count;
  978.   kern_return_t ret;
  979.   int index;
  980.   thread_t new_thread = MACH_PORT_NULL;
  981.  
  982.   if (thread_id < 0)
  983.     error ("Can't select cprocs without kernel thread");
  984.  
  985.   ret = task_threads (task, &thread_list, &thread_count);
  986.   if (ret != KERN_SUCCESS)
  987.     {
  988.       warning ("Can not select a thread from a dead task");
  989.       kill_inferior ();
  990.       return KERN_FAILURE;
  991.     }
  992.  
  993.   if (thread_count == 0)
  994.     {
  995.       /* The task can not do anything anymore, but it still
  996.        * exists as a container for memory and ports.
  997.        */
  998.       registers_changed ();
  999.       warning ("Task %d has no threads",
  1000.            map_port_name_to_mid (task, MACH_TYPE_TASK));
  1001.       current_thread = MACH_PORT_NULL;
  1002.       (void) vm_deallocate(mach_task_self(),
  1003.                (vm_address_t) thread_list,
  1004.                (thread_count * sizeof(mach_port_t)));
  1005.       return KERN_FAILURE;
  1006.     }
  1007.  
  1008.   if (! thread_id || flag == 2)
  1009.     {
  1010.       /* First thread or a slotnumber */
  1011.       if (! thread_id)
  1012.     new_thread = thread_list[0];
  1013.       else
  1014.     {
  1015.       if (thread_id < thread_count)
  1016.         new_thread = thread_list[ thread_id ];
  1017.       else
  1018.         {
  1019.           (void) vm_deallocate(mach_task_self(),
  1020.                    (vm_address_t) thread_list,
  1021.                    (thread_count * sizeof(mach_port_t)));
  1022.           error ("No such thread slot number : %d", thread_id);
  1023.         }
  1024.     }
  1025.     }
  1026.   else
  1027.     {
  1028.       for (index = 0; index < thread_count; index++)
  1029.     if (thread_id == map_port_name_to_mid (thread_list [index],
  1030.                            MACH_TYPE_THREAD))
  1031.       {
  1032.         new_thread = thread_list [index];
  1033.         index = -1;
  1034.         break;
  1035.       }
  1036.       
  1037.       if (index != -1)
  1038.     error ("No thread with mid %d", thread_id);
  1039.     }
  1040.   
  1041.   /* Notify when the selected thread dies */
  1042.   request_notify (new_thread, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_THREAD);
  1043.   
  1044.   ret = vm_deallocate(mach_task_self(),
  1045.               (vm_address_t) thread_list,
  1046.               (thread_count * sizeof(mach_port_t)));
  1047.   CHK ("vm_deallocate", ret);
  1048.   
  1049.   if (! flag)
  1050.     current_thread = new_thread;
  1051.   else
  1052.     {
  1053. #if 0
  1054.       if (MACH_PORT_VALID (current_thread))
  1055.     {
  1056.       /* Store the gdb's view of the thread we are deselecting
  1057.        *
  1058.        * @@ I think gdb updates registers immediately when they are
  1059.        * changed, so don't do this.
  1060.        */
  1061.       ret = thread_abort (current_thread);
  1062.       CHK ("Could not abort system calls when saving state of old thread",
  1063.            ret);
  1064.       target_prepare_to_store ();
  1065.       target_store_registers (-1);
  1066.     }
  1067. #endif
  1068.  
  1069.       registers_changed ();
  1070.  
  1071.       current_thread = new_thread;
  1072.  
  1073.       ret = thread_abort (current_thread);
  1074.       CHK ("Could not abort system calls when selecting a thread", ret);
  1075.  
  1076.       stop_pc = read_pc();
  1077.       set_current_frame (create_new_frame (read_register (FP_REGNUM),
  1078.                        stop_pc));
  1079.  
  1080.       select_frame (get_current_frame (), 0);
  1081.  
  1082.       stop_frame_address = FRAME_FP (get_current_frame ());
  1083.     }
  1084.  
  1085.   return KERN_SUCCESS;
  1086. }
  1087.  
  1088. /*
  1089.  * Switch to use thread named NEW_THREAD.
  1090.  * Return it's MID
  1091.  */
  1092. int
  1093. switch_to_thread (new_thread)
  1094.      thread_t new_thread;
  1095. {
  1096.   thread_t saved_thread = current_thread;
  1097.   int mid;
  1098.  
  1099.   mid = map_port_name_to_mid (new_thread,
  1100.                   MACH_TYPE_THREAD);
  1101.   if (mid == -1)
  1102.     warning ("Can't map thread name 0x%x to mid", new_thread);
  1103.   else if (select_thread (inferior_task, mid, 1) != KERN_SUCCESS)
  1104.     {
  1105.       if (current_thread)
  1106.     current_thread = saved_thread;
  1107.       error ("Could not select thread %d", mid);
  1108.     }
  1109.     
  1110.   return mid;
  1111. }
  1112.  
  1113. /* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
  1114.  * Note that the registers are not yet valid in the inferior task.
  1115.  */
  1116. static void
  1117. m3_trace_him (pid)
  1118.      int pid;
  1119. {
  1120.   kern_return_t ret;
  1121.  
  1122.   inferior_task = task_by_pid (pid);
  1123.  
  1124.   if (! MACH_PORT_VALID (inferior_task))
  1125.     error ("Can not map Unix pid %d to Mach task", pid);
  1126.  
  1127.   /* Clean up previous notifications and create new ones */
  1128.   setup_notify_port (1);
  1129.  
  1130.   /* When notification appears, the inferior task has died */
  1131.   request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
  1132.  
  1133.   emulator_present = have_emulator_p (inferior_task);
  1134.  
  1135.   /* By default, select the first thread,
  1136.    * If task has no threads, gives a warning
  1137.    * Does not fetch registers, since they are not yet valid.
  1138.    */
  1139.   select_thread (inferior_task, 0, 0);
  1140.  
  1141.   inferior_exception_port = MACH_PORT_NULL;
  1142.  
  1143.   setup_exception_port ();
  1144.  
  1145.   xx_debug ("Now the debugged task is created\n");
  1146.  
  1147.   /* One trap to exec the shell, one to exec the program being debugged.  */
  1148.   intercept_exec_calls (2);
  1149. }
  1150.  
  1151. setup_exception_port ()
  1152. {
  1153.   kern_return_t ret;
  1154.  
  1155.   ret = mach_port_allocate (mach_task_self(), 
  1156.                 MACH_PORT_RIGHT_RECEIVE,
  1157.                 &inferior_exception_port);
  1158.   CHK("mach_port_allocate",ret);
  1159.  
  1160.   /* add send right */
  1161.   ret = mach_port_insert_right (mach_task_self (),
  1162.                 inferior_exception_port,
  1163.                 inferior_exception_port,
  1164.                 MACH_MSG_TYPE_MAKE_SEND);
  1165.   CHK("mach_port_insert_right",ret);
  1166.  
  1167.   ret = mach_port_move_member (mach_task_self(), 
  1168.                    inferior_exception_port,
  1169.                    inferior_wait_port_set);
  1170.   CHK("mach_port_move_member",ret);
  1171.  
  1172.   ret = task_get_special_port (inferior_task, 
  1173.                    TASK_EXCEPTION_PORT,
  1174.                    &inferior_old_exception_port);
  1175.   CHK ("task_get_special_port(old exc)",ret);
  1176.  
  1177.   ret = task_set_special_port (inferior_task,
  1178.                    TASK_EXCEPTION_PORT, 
  1179.                    inferior_exception_port);
  1180.   CHK("task_set_special_port",ret);
  1181.  
  1182.   ret = mach_port_deallocate (mach_task_self (),
  1183.                   inferior_exception_port);
  1184.   CHK("mack_port_deallocate",ret);
  1185.  
  1186. #if 0
  1187.   /* When notify appears, the inferior_task's exception
  1188.    * port has been destroyed.
  1189.    *
  1190.    * Not used, since the dead_name_notification already
  1191.    * appears when task dies.
  1192.    *
  1193.    */
  1194.   request_notify (inferior_exception_port,
  1195.           MACH_NOTIFY_NO_SENDERS,
  1196.           MACH_TYPE_EXCEPTION_PORT);
  1197. #endif
  1198. }
  1199.  
  1200. /* Nonzero if gdb is waiting for a message */
  1201. int mach_really_waiting;
  1202.  
  1203. /* Wait for the inferior to stop for some reason.
  1204.    - Loop on notifications until inferior_task dies.
  1205.    - Loop on exceptions until stopped_in_exception comes true.
  1206.      (e.g. we receive a single step trace trap)
  1207.    - a message arrives to gdb's message port
  1208.  
  1209.    There is no other way to exit this loop.
  1210.  
  1211.    Returns the inferior_pid for rest of gdb.
  1212.    Side effects: Set *OURSTATUS.  */
  1213. int
  1214. mach_really_wait (w)
  1215.      struct target_waitstatus *ourstatus;
  1216. {
  1217.   int pid;
  1218.   kern_return_t ret;
  1219.   int w;
  1220.  
  1221.   struct msg {
  1222.     mach_msg_header_t    header;
  1223.     mach_msg_type_t foo;
  1224.     int             data[8000];
  1225.   } in_msg, out_msg;
  1226.  
  1227.   /* Either notify (death), exception or message can stop the inferior */
  1228.   stopped_in_exception = FALSE;
  1229.  
  1230.   while (1)
  1231.     {
  1232.       QUIT;
  1233.  
  1234.       stop_exception = stop_code = stop_subcode = -1;
  1235.       stop_thread = MACH_PORT_NULL;
  1236.  
  1237.       mach_really_waiting = 1;
  1238.       ret = mach_msg (&in_msg.header,        /* header */
  1239.               MACH_RCV_MSG,        /* options */
  1240.               0,            /* send size */
  1241.               sizeof (struct msg),    /* receive size */
  1242.               currently_waiting_for,    /* receive name */
  1243.               MACH_MSG_TIMEOUT_NONE,
  1244.               MACH_PORT_NULL);
  1245.       mach_really_waiting = 0;
  1246.       CHK("mach_msg (receive)", ret);
  1247.  
  1248.       /* Check if we received a notify of the childs' death */
  1249.       if (notify_server (&in_msg.header, &out_msg.header))
  1250.     {
  1251.       /* If inferior_task is null then the inferior has
  1252.          gone away and we want to return to command level.
  1253.          Otherwise it was just an informative message and we
  1254.          need to look to see if there are any more. */
  1255.       if (inferior_task != MACH_PORT_NULL)
  1256.         continue;
  1257.       else
  1258.         {
  1259.           /* Collect Unix exit status for gdb */
  1260.  
  1261.           wait3(&w, WNOHANG, 0);
  1262.  
  1263.           /* This mess is here to check that the rest of
  1264.            * gdb knows that the inferior died. It also
  1265.            * tries to hack around the fact that Mach 3.0 (mk69)
  1266.            * unix server (ux28) does not always know what
  1267.            * has happened to it's children when mach-magic
  1268.            * is applied on them.
  1269.            */
  1270.           if ((!WIFEXITED(w) && WIFSTOPPED(w))         ||
  1271.           (WIFEXITED(w)  && WEXITSTATUS(w) > 0377))
  1272.         {
  1273.           WSETEXIT(w, 0);
  1274.           warning ("Using exit value 0 for terminated task");
  1275.         }
  1276.           else if (!WIFEXITED(w))
  1277.         {
  1278.           int sig = WTERMSIG(w);
  1279.  
  1280.           /* Signals cause problems. Warn the user. */
  1281.           if (sig != SIGKILL) /* Bad luck if garbage matches this */
  1282.             warning ("The terminating signal stuff may be nonsense");
  1283.           else if (sig > NSIG)
  1284.             {
  1285.               WSETEXIT(w, 0);
  1286.               warning ("Using exit value 0 for terminated task");
  1287.             }
  1288.         }
  1289.           store_waitstatus (ourstatus, w);
  1290.           return inferior_pid;
  1291.         }
  1292.     }
  1293.  
  1294.       /* Hmm. Check for exception, as it was not a notification.
  1295.      exc_server() does an upcall to catch_exception_raise()
  1296.      if this rpc is an exception. Further actions are decided
  1297.      there.
  1298.        */
  1299.       if (! exc_server (&in_msg.header, &out_msg.header))
  1300.     {
  1301.  
  1302.       /* Not an exception, check for message.
  1303.        *
  1304.        * Messages don't come from the inferior, or if they
  1305.        * do they better be asynchronous or it will hang.
  1306.        */
  1307.       if (gdb_message_server (&in_msg.header))
  1308.         continue;
  1309.  
  1310.       error ("Unrecognized message received in mach_really_wait");
  1311.     }
  1312.  
  1313.       /* Send the reply of the exception rpc to the suspended task */
  1314.       ret = mach_msg_send (&out_msg.header);
  1315.       CHK ("mach_msg_send (exc reply)", ret);
  1316.       
  1317.       if (stopped_in_exception)
  1318.     {
  1319.       /* Get unix state. May be changed in mach3_exception_actions() */
  1320.       wait3(&w, WNOHANG, 0);
  1321.  
  1322.       mach3_exception_actions (&w, FALSE, "Task");
  1323.  
  1324.       store_waitstatus (ourstatus, w);
  1325.       return inferior_pid;
  1326.     }
  1327.     }
  1328. }
  1329.  
  1330. /* Called by macro DO_QUIT() in utils.c(quit).
  1331.  * This is called just before calling error() to return to command level
  1332.  */
  1333. void
  1334. mach3_quit ()
  1335. {
  1336.   int mid;
  1337.   kern_return_t ret;
  1338.   
  1339.   if (mach_really_waiting)
  1340.     {
  1341.       ret = task_suspend (inferior_task);
  1342.       
  1343.       if (ret != KERN_SUCCESS)
  1344.     {
  1345.       warning ("Could not suspend task for interrupt: %s",
  1346.            mach_error_string (ret));
  1347.       mach_really_waiting = 0;
  1348.       return;
  1349.     }
  1350.     }
  1351.  
  1352.   must_suspend_thread = 0;
  1353.   mach_really_waiting = 0;
  1354.  
  1355.   mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
  1356.   if (mid == -1)
  1357.     {
  1358.       warning ("Selecting first existing kernel thread");
  1359.       mid = 0;
  1360.     }
  1361.  
  1362.   current_thread = MACH_PORT_NULL; /* Force setup */
  1363.   select_thread (inferior_task, mid, 1);
  1364.  
  1365.   return;
  1366. }
  1367.  
  1368. /* If ^C is typed when we are waiting for a message
  1369.  * and your Unix server is able to notice that we 
  1370.  * should quit now.
  1371.  *
  1372.  * Called by REQUEST_QUIT() from utils.c(request_quit)
  1373.  */
  1374. void
  1375. mach3_request_quit ()
  1376. {
  1377.   if (mach_really_waiting)
  1378.     immediate_quit = 1;
  1379. }      
  1380.  
  1381. /*
  1382.  * Gdb message server.
  1383.  * Currently implemented is the STOP message, that causes
  1384.  * gdb to return to the command level like ^C had been typed from terminal.
  1385.  */
  1386. int
  1387. gdb_message_server (InP)
  1388.      mach_msg_header_t *InP;
  1389. {
  1390.   kern_return_t ret;
  1391.   int mid;
  1392.  
  1393.   if (InP->msgh_local_port == our_message_port)
  1394.     {
  1395.       /* A message coming to our_message_port. Check validity */
  1396.       switch (InP->msgh_id) {
  1397.  
  1398.       case GDB_MESSAGE_ID_STOP:
  1399.     ret = task_suspend (inferior_task);
  1400.     if (ret != KERN_SUCCESS)
  1401.       warning ("Could not suspend task for stop message: %s",
  1402.            mach_error_string (ret));
  1403.  
  1404.     /* QUIT in mach_really_wait() loop. */
  1405.     request_quit (0);
  1406.     break;
  1407.  
  1408.       default:
  1409.     warning ("Invalid message id %d received, ignored.",
  1410.          InP->msgh_id);
  1411.     break;
  1412.       }
  1413.  
  1414.       return 1;
  1415.     }
  1416.  
  1417.   /* Message not handled by this server */
  1418.   return 0;
  1419. }
  1420.  
  1421. /* NOTE: This is not an RPC call. It is a simpleroutine.
  1422.  *
  1423.  * This is not called from this gdb code.
  1424.  *
  1425.  * It may be called by another debugger to cause this
  1426.  * debugger to enter command level:
  1427.  *
  1428.  *            (gdb) set stop_inferior_gdb ()
  1429.  *            (gdb) continue
  1430.  *
  1431.  * External program "stop-gdb" implements this also.
  1432.  */
  1433. void
  1434. stop_inferior_gdb ()
  1435. {
  1436.   kern_return_t ret;
  1437.  
  1438.   /* Code generated by mig, with minor cleanups :-)
  1439.    *
  1440.    * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
  1441.    */
  1442.  
  1443.   typedef struct {
  1444.     mach_msg_header_t Head;
  1445.   } Request;
  1446.  
  1447.   Request Mess;
  1448.  
  1449.   register Request *InP = &Mess;
  1450.  
  1451.   InP->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
  1452.  
  1453.   /* msgh_size passed as argument */
  1454.   InP->Head.msgh_remote_port = our_message_port;
  1455.   InP->Head.msgh_local_port  = MACH_PORT_NULL;
  1456.   InP->Head.msgh_seqno       = 0;
  1457.   InP->Head.msgh_id          = GDB_MESSAGE_ID_STOP;
  1458.  
  1459.   ret = mach_msg (&InP->Head,
  1460.           MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
  1461.           sizeof(Request),
  1462.           0,
  1463.           MACH_PORT_NULL,
  1464.           MACH_MSG_TIMEOUT_NONE,
  1465.           MACH_PORT_NULL);
  1466. }
  1467.  
  1468. #ifdef THREAD_ALLOWED_TO_BREAK
  1469. /*
  1470.  * Return 1 if the MID specifies the thread that caused the
  1471.  * last exception.
  1472.  *  Since catch_exception_raise() selects the thread causing
  1473.  * the last exception to current_thread, we just check that
  1474.  * it is selected and the last exception was a breakpoint.
  1475.  */
  1476. int
  1477. mach_thread_for_breakpoint (mid)
  1478.      int mid;
  1479. {
  1480.   int cmid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
  1481.  
  1482.   if (mid < 0)
  1483.     {
  1484.       mid = map_slot_to_mid (-(mid+1), 0, 0);
  1485.       if (mid < 0)
  1486.     return 0;        /* Don't stop, no such slot */
  1487.     }
  1488.  
  1489.   if (! mid || cmid == -1)
  1490.     return 1;    /* stop */
  1491.  
  1492.   return cmid == mid && stop_exception == EXC_BREAKPOINT;
  1493. }
  1494. #endif /* THREAD_ALLOWED_TO_BREAK */
  1495.  
  1496. #ifdef THREAD_PARSE_ID
  1497. /*
  1498.  * Map a thread id string (MID or a @SLOTNUMBER)
  1499.  * to a thread-id.
  1500.  *
  1501.  *   0  matches all threads.
  1502.  *   Otherwise the meaning is defined only in this file.
  1503.  *   (mach_thread_for_breakpoint uses it)
  1504.  *
  1505.  * @@ This allows non-existent MIDs to be specified.
  1506.  *    It now also allows non-existent slots to be
  1507.  *    specified. (Slot numbers stored are negative,
  1508.  *    and the magnitude is one greater than the actual
  1509.  *    slot index. (Since 0 is reserved))
  1510.  */
  1511. int
  1512. mach_thread_parse_id (arg)
  1513.      char *arg;
  1514. {
  1515.   int mid;
  1516.   if (arg == 0)
  1517.     error ("thread id excpected");
  1518.   mid = parse_thread_id (arg, 0, 1);
  1519.  
  1520.   return mid;
  1521. }
  1522. #endif /* THREAD_PARSE_ID */
  1523.  
  1524. #ifdef THREAD_OUTPUT_ID
  1525. char *
  1526. mach_thread_output_id (mid)
  1527.      int mid;
  1528. {
  1529.   static char foobar [20];
  1530.  
  1531.   if (mid > 0)
  1532.     sprintf (foobar, "mid %d", mid);
  1533.   else if (mid < 0)
  1534.     sprintf (foobar, "@%d", -(mid+1));
  1535.   else
  1536.     sprintf (foobar, "*any thread*");
  1537.  
  1538.   return foobar;
  1539. }
  1540. #endif /* THREAD_OUTPUT_ID */
  1541.  
  1542. /* Called with hook PREPARE_TO_PROCEED() from infrun.c.
  1543.  *
  1544.  * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
  1545.  *
  1546.  *  if SELECT_IT is nonzero, reselect the thread that was active when
  1547.  *  we stopped at a breakpoint.
  1548.  *
  1549.  */
  1550.  
  1551. mach3_prepare_to_proceed (select_it)
  1552.      int select_it;
  1553. {
  1554.   if (stop_thread &&
  1555.       stop_thread != current_thread &&
  1556.       stop_exception == EXC_BREAKPOINT)
  1557.     {
  1558.       int mid;
  1559.  
  1560.       if (! select_it)
  1561.     return 1;
  1562.  
  1563.       mid = switch_to_thread (stop_thread);
  1564.  
  1565.       return 1;
  1566.     }
  1567.  
  1568.   return 0;
  1569. }
  1570.  
  1571. /* this stuff here is an upcall via libmach/excServer.c 
  1572.    and mach_really_wait which does the actual upcall.
  1573.  
  1574.    The code will pass the exception to the inferior if:
  1575.  
  1576.      - The task that signaled is not the inferior task
  1577.        (e.g. when debugging another debugger)
  1578.  
  1579.      - The user has explicitely requested to pass on the exceptions.
  1580.        (e.g to the default unix exception handler, which maps
  1581.     exceptions to signals, or the user has her own exception handler)
  1582.  
  1583.      - If the thread that signaled is being single-stepped and it
  1584.        has set it's own exception port and the exception is not
  1585.        EXC_BREAKPOINT. (Maybe this is not desirable?)
  1586.  */
  1587.  
  1588. kern_return_t
  1589. catch_exception_raise (port, thread, task, exception, code, subcode)
  1590.      mach_port_t port;
  1591.      thread_t thread;
  1592.      task_t task;
  1593.      int exception, code, subcode;
  1594. {
  1595.   kern_return_t ret;
  1596.   boolean_t signal_thread;
  1597.   int mid = map_port_name_to_mid (thread, MACH_TYPE_THREAD);
  1598.  
  1599.   if (! MACH_PORT_VALID (thread))
  1600.     {
  1601.       /* If the exception was sent and thread dies before we
  1602.      receive it, THREAD will be MACH_PORT_DEAD
  1603.        */
  1604.  
  1605.       current_thread = thread = MACH_PORT_NULL;
  1606.       error ("Received exception from nonexistent thread");
  1607.     }
  1608.  
  1609.   /* Check if the task died in transit.
  1610.    * @@ Isn't the thread also invalid in such case?
  1611.    */
  1612.   if (! MACH_PORT_VALID (task))
  1613.     {
  1614.       current_thread = thread = MACH_PORT_NULL;
  1615.       error ("Received exception from nonexistent task");
  1616.     }
  1617.  
  1618.   if (exception < 0 || exception > MAX_EXCEPTION)
  1619.     fatal ("catch_exception_raise: unknown exception code %d thread %d",
  1620.        exception,
  1621.        mid);
  1622.  
  1623.   if (! MACH_PORT_VALID (inferior_task))
  1624.     error ("got an exception, but inferior_task is null or dead");
  1625.   
  1626.   stop_exception = exception;
  1627.   stop_code      = code;
  1628.   stop_subcode   = subcode;  
  1629.   stop_thread    = thread;
  1630.   
  1631.   signal_thread = exception != EXC_BREAKPOINT       &&
  1632.               port == singlestepped_thread_port &&
  1633.           MACH_PORT_VALID (thread_saved_exception_port);
  1634.  
  1635.   /* If it was not our inferior or if we want to forward
  1636.    * the exception to the inferior's handler, do it here
  1637.    *
  1638.    * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
  1639.    */
  1640.   if (task != inferior_task ||
  1641.       signal_thread         ||
  1642.       exception_map [exception].forward)
  1643.     {
  1644.       mach_port_t eport = inferior_old_exception_port;
  1645.  
  1646.       if (signal_thread)
  1647.     {
  1648.       /*
  1649.         GDB now forwards the exeption to thread's original handler,
  1650.         since the user propably knows what he is doing.
  1651.         Give a message, though.
  1652.        */
  1653.  
  1654.       mach3_exception_actions ((WAITTYPE *)NULL, TRUE, "Thread");
  1655.       eport = thread_saved_exception_port;
  1656.     }
  1657.  
  1658.       /* Send the exception to the original handler */
  1659.       ret = exception_raise (eport,
  1660.                  thread, 
  1661.                  task,
  1662.                  exception,
  1663.                  code,
  1664.                  subcode);
  1665.  
  1666.       (void) mach_port_deallocate (mach_task_self (), task);
  1667.       (void) mach_port_deallocate (mach_task_self (), thread);
  1668.  
  1669.       /* If we come here, we don't want to trace any more, since we
  1670.        * will never stop for tracing anyway.
  1671.        */
  1672.       discard_single_step (thread);
  1673.  
  1674.       /* Do not stop the inferior */
  1675.       return ret;
  1676.     }
  1677.   
  1678.   /* Now gdb handles the exception */
  1679.   stopped_in_exception = TRUE;
  1680.  
  1681.   ret = task_suspend (task);
  1682.   CHK ("Error suspending inferior after exception", ret);
  1683.  
  1684.   must_suspend_thread = 0;
  1685.  
  1686.   if (current_thread != thread)
  1687.     {
  1688.       if (MACH_PORT_VALID (singlestepped_thread_port))
  1689.     /* Cleanup discards single stepping */
  1690.     error ("Exception from thread %d while singlestepping thread %d",
  1691.            mid,
  1692.            map_port_name_to_mid (current_thread, MACH_TYPE_THREAD));
  1693.       
  1694.       /* Then select the thread that caused the exception */
  1695.       if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
  1696.     error ("Could not select thread %d causing exception", mid);
  1697.       else
  1698.     warning ("Gdb selected thread %d", mid);
  1699.     }
  1700.  
  1701.   /* If we receive an exception that is not breakpoint
  1702.    * exception, we interrupt the single step and return to
  1703.    * debugger. Trace condition is cleared.
  1704.    */
  1705.   if (MACH_PORT_VALID (singlestepped_thread_port))
  1706.     {
  1707.       if (stop_exception != EXC_BREAKPOINT)
  1708.     warning ("Single step interrupted by exception");
  1709.       else if (port == singlestepped_thread_port)
  1710.     {
  1711.       /* Single step exception occurred, remove trace bit
  1712.        * and return to gdb.
  1713.        */
  1714.       if (! MACH_PORT_VALID (current_thread))
  1715.         error ("Single stepped thread is not valid");
  1716.     
  1717.       /* Resume threads, but leave the task suspended */
  1718.       resume_all_threads (0);
  1719.     }
  1720.       else
  1721.     warning ("Breakpoint while single stepping?");
  1722.  
  1723.       discard_single_step (current_thread);
  1724.     }
  1725.   
  1726.   (void) mach_port_deallocate (mach_task_self (), task);
  1727.   (void) mach_port_deallocate (mach_task_self (), thread);
  1728.  
  1729.   return KERN_SUCCESS;
  1730. }
  1731.  
  1732. int
  1733. port_valid (port, mask)
  1734.   mach_port_t port;
  1735.   int         mask;
  1736. {
  1737.   kern_return_t ret;
  1738.   mach_port_type_t type;
  1739.  
  1740.   ret = mach_port_type (mach_task_self (),
  1741.             port,
  1742.             &type);
  1743.   if (ret != KERN_SUCCESS || (type & mask) != mask)
  1744.     return 0;
  1745.   return 1;
  1746. }
  1747.  
  1748. /* @@ No vm read cache implemented yet */
  1749. boolean_t vm_read_cache_valid = FALSE;
  1750.  
  1751. /*
  1752.  * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
  1753.  * in gdb's address space.
  1754.  *
  1755.  * Return 0 on failure; number of bytes read otherwise.
  1756.  */
  1757. int
  1758. mach3_read_inferior (addr, myaddr, length)
  1759.      CORE_ADDR addr;
  1760.      char *myaddr;
  1761.      int length;
  1762. {
  1763.   kern_return_t ret;
  1764.   vm_address_t low_address       = (vm_address_t) trunc_page (addr);
  1765.   vm_size_t    aligned_length = 
  1766.                 (vm_size_t) round_page (addr+length) - low_address;
  1767.   pointer_t    copied_memory;
  1768.   int           copy_count;
  1769.  
  1770.   /* Get memory from inferior with page aligned addresses */
  1771.   ret = vm_read (inferior_task,
  1772.          low_address,
  1773.          aligned_length,
  1774.          &copied_memory,
  1775.          ©_count);
  1776.   if (ret != KERN_SUCCESS)
  1777.     {
  1778.       /* the problem is that the inferior might be killed for whatever reason
  1779.        * before we go to mach_really_wait. This is one place that ought to
  1780.        * catch many of those errors.
  1781.        * @@ A better fix would be to make all external events to GDB
  1782.        * to arrive via a SINGLE port set. (Including user input!)
  1783.        */
  1784.  
  1785.       if (! port_valid (inferior_task, MACH_PORT_TYPE_SEND))
  1786.     {
  1787.       kill_inferior ();
  1788.       error ("Inferior killed (task port invalid)");
  1789.     }
  1790.       else
  1791.     {
  1792. #ifdef OSF
  1793.       extern int errno;
  1794.       /* valprint.c gives nicer format if this does not
  1795.          screw it. Eamonn seems to like this, so I enable
  1796.          it if OSF is defined...
  1797.        */
  1798.       warning ("[read inferior %x failed: %s]",
  1799.            addr, mach_error_string (ret));
  1800.       errno = 0;
  1801. #endif
  1802.       return 0;
  1803.     }
  1804.     }
  1805.  
  1806.   memcpy (myaddr, (char *)addr - low_address + copied_memory, length);
  1807.  
  1808.   ret = vm_deallocate (mach_task_self (),
  1809.                copied_memory,
  1810.                copy_count);
  1811.   CHK("mach3_read_inferior vm_deallocate failed", ret);
  1812.  
  1813.   return length;
  1814. }
  1815.  
  1816. #ifdef __STDC__
  1817. #define CHK_GOTO_OUT(str,ret) \
  1818.   do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
  1819. #else
  1820. #define CHK_GOTO_OUT(str,ret) \
  1821.   do if (ret != KERN_SUCCESS) { errstr = str; goto out; } while(0)
  1822. #endif
  1823.  
  1824. struct vm_region_list {
  1825.   struct vm_region_list *next;
  1826.   vm_prot_t    protection;
  1827.   vm_address_t  start;
  1828.   vm_size_t    length;
  1829. };
  1830.  
  1831. struct obstack  region_obstack;
  1832.  
  1833. /*
  1834.  * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
  1835.  * in gdb's address space.
  1836.  */
  1837. int
  1838. mach3_write_inferior (addr, myaddr, length)
  1839.      CORE_ADDR addr;
  1840.      char *myaddr;
  1841.      int length;
  1842. {
  1843.   kern_return_t ret;
  1844.   vm_address_t low_address       = (vm_address_t) trunc_page (addr);
  1845.   vm_size_t    aligned_length = 
  1846.                 (vm_size_t) round_page (addr+length) - low_address;
  1847.   pointer_t    copied_memory;
  1848.   int           copy_count;
  1849.   int           deallocate = 0;
  1850.  
  1851.   char         *errstr = "Bug in mach3_write_inferior";
  1852.  
  1853.   struct vm_region_list *region_element;
  1854.   struct vm_region_list *region_head = (struct vm_region_list *)NULL;
  1855.  
  1856.   /* Get memory from inferior with page aligned addresses */
  1857.   ret = vm_read (inferior_task,
  1858.          low_address,
  1859.          aligned_length,
  1860.          &copied_memory,
  1861.          ©_count);
  1862.   CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret);
  1863.  
  1864.   deallocate++;
  1865.  
  1866.   memcpy ((char *)addr - low_address + copied_memory, myaddr, length);
  1867.  
  1868.   obstack_init (®ion_obstack);
  1869.  
  1870.   /* Do writes atomically.
  1871.    * First check for holes and unwritable memory.
  1872.    */
  1873.   {
  1874.     vm_size_t    remaining_length  = aligned_length;
  1875.     vm_address_t region_address    = low_address;
  1876.  
  1877.     struct vm_region_list *scan;
  1878.  
  1879.     while(region_address < low_address + aligned_length)
  1880.       {
  1881.     vm_prot_t protection;
  1882.     vm_prot_t max_protection;
  1883.     vm_inherit_t inheritance;
  1884.     boolean_t shared;
  1885.     mach_port_t object_name;
  1886.     vm_offset_t offset;
  1887.     vm_size_t   region_length = remaining_length;
  1888.     vm_address_t old_address  = region_address;
  1889.     
  1890.     ret = vm_region (inferior_task,
  1891.              ®ion_address,
  1892.              ®ion_length,
  1893.              &protection,
  1894.              &max_protection,
  1895.              &inheritance,
  1896.              &shared,
  1897.              &object_name,
  1898.              &offset);
  1899.     CHK_GOTO_OUT ("vm_region failed", ret);
  1900.  
  1901.     /* Check for holes in memory */
  1902.     if (old_address != region_address)
  1903.       {
  1904.         warning ("No memory at 0x%x. Nothing written",
  1905.              old_address);
  1906.         ret = KERN_SUCCESS;
  1907.         length = 0;
  1908.         goto out;
  1909.       }
  1910.  
  1911.     if (!(max_protection & VM_PROT_WRITE))
  1912.       {
  1913.         warning ("Memory at address 0x%x is unwritable. Nothing written",
  1914.              old_address);
  1915.         ret = KERN_SUCCESS;
  1916.         length = 0;
  1917.         goto out;
  1918.       }
  1919.  
  1920.     /* Chain the regions for later use */
  1921.     region_element = 
  1922.       (struct vm_region_list *)
  1923.         obstack_alloc (®ion_obstack, sizeof (struct vm_region_list));
  1924.     
  1925.     region_element->protection = protection;
  1926.     region_element->start      = region_address;
  1927.     region_element->length     = region_length;
  1928.  
  1929.     /* Chain the regions along with protections */
  1930.     region_element->next = region_head;
  1931.     region_head          = region_element;
  1932.     
  1933.     region_address += region_length;
  1934.     remaining_length = remaining_length - region_length;
  1935.       }
  1936.  
  1937.     /* If things fail after this, we give up.
  1938.      * Somebody is messing up inferior_task's mappings.
  1939.      */
  1940.     
  1941.     /* Enable writes to the chained vm regions */
  1942.     for (scan = region_head; scan; scan = scan->next)
  1943.       {
  1944.     boolean_t protection_changed = FALSE;
  1945.     
  1946.     if (!(scan->protection & VM_PROT_WRITE))
  1947.       {
  1948.         ret = vm_protect (inferior_task,
  1949.                   scan->start,
  1950.                   scan->length,
  1951.                   FALSE,
  1952.                   scan->protection | VM_PROT_WRITE);
  1953.         CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
  1954.       }
  1955.       }
  1956.  
  1957.     ret = vm_write (inferior_task,
  1958.             low_address,
  1959.             copied_memory,
  1960.             aligned_length);
  1961.     CHK_GOTO_OUT ("vm_write failed", ret);
  1962.     
  1963.     /* Set up the original region protections, if they were changed */
  1964.     for (scan = region_head; scan; scan = scan->next)
  1965.       {
  1966.     boolean_t protection_changed = FALSE;
  1967.     
  1968.     if (!(scan->protection & VM_PROT_WRITE))
  1969.       {
  1970.         ret = vm_protect (inferior_task,
  1971.                   scan->start,
  1972.                   scan->length,
  1973.                   FALSE,
  1974.                   scan->protection);
  1975.         CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
  1976.       }
  1977.       }
  1978.   }
  1979.  
  1980.  out:
  1981.   if (deallocate)
  1982.     {
  1983.       obstack_free (®ion_obstack, 0);
  1984.       
  1985.       (void) vm_deallocate (mach_task_self (),
  1986.                 copied_memory,
  1987.                 copy_count);
  1988.     }
  1989.  
  1990.   if (ret != KERN_SUCCESS)
  1991.     {
  1992.       warning ("%s %s", errstr, mach_error_string (ret));
  1993.       return 0;
  1994.     }
  1995.  
  1996.   return length;
  1997. }
  1998.  
  1999. /* Return 0 on failure, number of bytes handled otherwise.  */
  2000. static int
  2001. m3_xfer_memory (memaddr, myaddr, len, write, target)
  2002.      CORE_ADDR memaddr;
  2003.      char *myaddr;
  2004.      int len;
  2005.      int write;
  2006.      struct target_ops *target;    /* IGNORED */
  2007. {
  2008.   int result;
  2009.  
  2010.   if (write)
  2011.     result = mach3_write_inferior (memaddr, myaddr, len);
  2012.   else
  2013.     result = mach3_read_inferior  (memaddr, myaddr, len);
  2014.  
  2015.   return result;
  2016. }
  2017.  
  2018.  
  2019. static char *
  2020. translate_state(state)
  2021. int    state;
  2022. {
  2023.   switch (state) {
  2024.   case TH_STATE_RUNNING:    return("R");
  2025.   case TH_STATE_STOPPED:    return("S");
  2026.   case TH_STATE_WAITING:    return("W");
  2027.   case TH_STATE_UNINTERRUPTIBLE: return("U");
  2028.   case TH_STATE_HALTED:        return("H");
  2029.   default:            return("?");
  2030.   }
  2031. }
  2032.  
  2033. static char *
  2034. translate_cstate (state)
  2035.      int state;
  2036. {
  2037.   switch (state)
  2038.     {
  2039.     case CPROC_RUNNING:    return "R";
  2040.     case CPROC_SWITCHING: return "S";
  2041.     case CPROC_BLOCKED: return "B";
  2042.     case CPROC_CONDWAIT: return "C";
  2043.     case CPROC_CONDWAIT|CPROC_SWITCHING: return "CS";
  2044.     default: return "?";
  2045.     }
  2046. }
  2047.  
  2048. /* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
  2049.  
  2050. mach_port_t           /* no mach_port_name_t found in include files. */
  2051. map_inferior_port_name (inferior_name, type)
  2052.      mach_port_t inferior_name;
  2053.      mach_msg_type_name_t type;
  2054. {
  2055.   kern_return_t        ret;
  2056.   mach_msg_type_name_t acquired;
  2057.   mach_port_t          iport;
  2058.   
  2059.   ret = mach_port_extract_right (inferior_task,
  2060.                  inferior_name,
  2061.                  type,
  2062.                  &iport,
  2063.                  &acquired);
  2064.   CHK("mach_port_extract_right (map_inferior_port_name)", ret);
  2065.  
  2066.   if (acquired != MACH_MSG_TYPE_PORT_SEND)
  2067.     error("Incorrect right extracted, (map_inferior_port_name)");
  2068.  
  2069.   ret = mach_port_deallocate (mach_task_self (),
  2070.                   iport);
  2071.   CHK ("Deallocating mapped port (map_inferior_port_name)", ret);
  2072.  
  2073.   return iport;
  2074. }
  2075.  
  2076. /*
  2077.  * Naming convention:
  2078.  *  Always return user defined name if found.
  2079.  *  _K == A kernel thread with no matching CPROC
  2080.  *  _C == A cproc with no current cthread
  2081.  *  _t == A cthread with no user defined name
  2082.  *
  2083.  * The digits that follow the _names are the SLOT number of the
  2084.  * kernel thread if there is such a thing, otherwise just a negation
  2085.  * of the sequential number of such cprocs.
  2086.  */
  2087.  
  2088. static char buf[7];
  2089.  
  2090. static char *
  2091. get_thread_name (one_cproc, id)
  2092.      gdb_thread_t one_cproc;
  2093.      int id;
  2094. {
  2095.   if (one_cproc)
  2096.     if (one_cproc->cthread == NULL)
  2097.       {
  2098.     /* cproc not mapped to any cthread */
  2099.     sprintf(buf, "_C%d", id);
  2100.       }
  2101.     else if (! one_cproc->cthread->name)
  2102.       {
  2103.     /* cproc and cthread, but no name */
  2104.     sprintf(buf, "_t%d", id);
  2105.       }
  2106.     else
  2107.       return (one_cproc->cthread->name);
  2108.   else
  2109.     {
  2110.       if (id < 0)
  2111.     warning ("Inconsistency in thread name id %d", id);
  2112.  
  2113.       /* Kernel thread without cproc */
  2114.       sprintf(buf, "_K%d", id);
  2115.     }
  2116.  
  2117.   return buf;
  2118. }
  2119.  
  2120. int
  2121. fetch_thread_info (task, mthreads_out)
  2122.      mach_port_t    task;
  2123.      gdb_thread_t    *mthreads_out;    /* out */
  2124. {
  2125.   kern_return_t  ret;
  2126.   thread_array_t th_table;
  2127.   int         th_count;
  2128.   gdb_thread_t mthreads = NULL;
  2129.   int          index;
  2130.  
  2131.   ret = task_threads (task, &th_table, &th_count);
  2132.   if (ret != KERN_SUCCESS)
  2133.     {
  2134.       warning ("Error getting inferior's thread list:%s",
  2135.            mach_error_string(ret));
  2136.       kill_inferior ();
  2137.       return -1;
  2138.     }
  2139.   
  2140.   mthreads = (gdb_thread_t)
  2141.             obstack_alloc
  2142.           (cproc_obstack,
  2143.            th_count * sizeof (struct gdb_thread));
  2144.  
  2145.   for (index = 0; index < th_count; index++)
  2146.     {
  2147.       thread_t saved_thread = MACH_PORT_NULL;
  2148.       int mid;
  2149.  
  2150.       if (must_suspend_thread)
  2151.     setup_thread (th_table[ index ], 1);
  2152.  
  2153.       if (th_table[index] != current_thread)
  2154.     {
  2155.       saved_thread = current_thread;
  2156.       
  2157.       mid = switch_to_thread (th_table[ index ]);
  2158.     }
  2159.  
  2160.       mthreads[index].name  = th_table[index];
  2161.       mthreads[index].cproc = NULL;    /* map_cprocs_to_kernel_threads() */
  2162.       mthreads[index].in_emulator = FALSE;
  2163.       mthreads[index].slotid = index;
  2164.       
  2165.       mthreads[index].sp = read_register (SP_REGNUM);
  2166.       mthreads[index].fp = read_register (FP_REGNUM);
  2167.       mthreads[index].pc = read_pc ();
  2168.  
  2169.       if (MACH_PORT_VALID (saved_thread))
  2170.     mid = switch_to_thread (saved_thread);
  2171.  
  2172.       if (must_suspend_thread)
  2173.     setup_thread (th_table[ index ], 0);
  2174.     }
  2175.   
  2176.   consume_send_rights (th_table, th_count);
  2177.   ret = vm_deallocate (mach_task_self(), (vm_address_t)th_table, 
  2178.                (th_count * sizeof(mach_port_t)));
  2179.   if (ret != KERN_SUCCESS)
  2180.     {
  2181.       warning ("Error trying to deallocate thread list : %s",
  2182.            mach_error_string (ret));
  2183.     }
  2184.  
  2185.   *mthreads_out = mthreads;
  2186.  
  2187.   return th_count;
  2188. }
  2189.  
  2190.  
  2191. /*
  2192.  * Current emulator always saves the USP on top of
  2193.  * emulator stack below struct emul_stack_top stuff.
  2194.  */
  2195. CORE_ADDR
  2196. fetch_usp_from_emulator_stack (sp)
  2197.      CORE_ADDR sp;
  2198. {
  2199.   CORE_ADDR stack_pointer;
  2200.  
  2201.   sp = (sp & ~(EMULATOR_STACK_SIZE-1)) +
  2202.         EMULATOR_STACK_SIZE - sizeof (struct emul_stack_top);
  2203.   
  2204.   if (mach3_read_inferior (sp,
  2205.                &stack_pointer,
  2206.                sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
  2207.     {
  2208.       warning ("Can't read user sp from emulator stack address 0x%x", sp);
  2209.       return 0;
  2210.     }
  2211.  
  2212.   return stack_pointer;
  2213. }
  2214.  
  2215. #ifdef MK67
  2216.  
  2217. /* get_emulation_vector() interface was changed after mk67 */
  2218. #define EMUL_VECTOR_COUNT 400    /* Value does not matter too much */
  2219.  
  2220. #endif /* MK67 */
  2221.  
  2222. /* Check if the emulator exists at task's address space.
  2223.  */
  2224. boolean_t
  2225. have_emulator_p (task)
  2226.      task_t task;
  2227. {
  2228.   kern_return_t    ret;
  2229. #ifndef EMUL_VECTOR_COUNT
  2230.   vm_offset_t    *emulation_vector;
  2231.   int        n;
  2232. #else
  2233.   vm_offset_t    emulation_vector[ EMUL_VECTOR_COUNT ];
  2234.   int        n = EMUL_VECTOR_COUNT;
  2235. #endif
  2236.   int        i;
  2237.   int        vector_start;
  2238.   
  2239.   ret = task_get_emulation_vector (task,
  2240.                    &vector_start,
  2241. #ifndef EMUL_VECTOR_COUNT
  2242.                    &emulation_vector,
  2243. #else
  2244.                    emulation_vector,
  2245. #endif
  2246.                    &n);
  2247.   CHK("task_get_emulation_vector", ret);
  2248.   xx_debug ("%d vectors from %d at 0x%08x\n",
  2249.         n, vector_start, emulation_vector);
  2250.   
  2251.   for(i = 0; i < n; i++)
  2252.     {
  2253.       vm_offset_t entry = emulation_vector [i];
  2254.  
  2255.       if (EMULATOR_BASE <= entry && entry <= EMULATOR_END)
  2256.     return TRUE;
  2257.       else if (entry)
  2258.     {
  2259.       static boolean_t informed = FALSE;
  2260.       if (!informed)
  2261.         {
  2262.           warning("Emulation vector address 0x08%x outside emulator space",
  2263.               entry);
  2264.           informed = TRUE;
  2265.         }
  2266.     }
  2267.     }
  2268.   return FALSE;
  2269. }
  2270.  
  2271. /* Map cprocs to kernel threads and vice versa.  */
  2272.  
  2273. void
  2274. map_cprocs_to_kernel_threads (cprocs, mthreads, thread_count)
  2275.      gdb_thread_t cprocs;
  2276.      gdb_thread_t mthreads;
  2277.      int thread_count;
  2278. {
  2279.   int index;
  2280.   gdb_thread_t scan;
  2281.   boolean_t all_mapped = TRUE;
  2282.  
  2283.   for (scan = cprocs; scan; scan = scan->next)
  2284.     {
  2285.       /* Default to: no kernel thread for this cproc */
  2286.       scan->reverse_map = -1;
  2287.  
  2288.       /* Check if the cproc is found by its stack */
  2289.       for (index = 0; index < thread_count; index++)
  2290.     {
  2291.       LONGEST stack_base =
  2292.         extract_signed_integer (scan.raw_cproc + CPROC_BASE_OFFSET,
  2293.                     CPROC_BASE_SIZE);
  2294.       LONGEST stack_size = 
  2295.         extract_signed_integer (scan.raw_cproc + CPROC_SIZE_OFFSET,
  2296.                     CPROC_SIZE_SIZE);
  2297.       if ((mthreads + index)->sp > stack_base &&
  2298.           (mthreads + index)->sp <= stack_base + stack_size)
  2299.         {
  2300.           (mthreads + index)->cproc = scan;
  2301.           scan->reverse_map = index;
  2302.           break;
  2303.         }
  2304.     }
  2305.       all_mapped &= (scan->reverse_map != -1);
  2306.     }
  2307.  
  2308.   /* Check for threads that are currently in the emulator.
  2309.    * If so, they have a different stack, and the still unmapped
  2310.    * cprocs may well get mapped to these threads.
  2311.    * 
  2312.    * If:
  2313.    *  - cproc stack does not match any kernel thread stack pointer
  2314.    *  - there is at least one extra kernel thread
  2315.    *    that has no cproc mapped above.
  2316.    *  - some kernel thread stack pointer points to emulator space
  2317.    *  then we find the user stack pointer saved in the emulator
  2318.    *  stack, and try to map that to the cprocs.
  2319.    *
  2320.    * Also set in_emulator for kernel threads.
  2321.    */ 
  2322.  
  2323.   if (emulator_present)
  2324.     {
  2325.       for (index = 0; index < thread_count; index++)
  2326.     {
  2327.       CORE_ADDR emul_sp;
  2328.       CORE_ADDR usp;
  2329.  
  2330.       gdb_thread_t mthread = (mthreads+index);
  2331.       emul_sp = mthread->sp;
  2332.  
  2333.       if (mthread->cproc == NULL &&
  2334.           EMULATOR_BASE <= emul_sp && emul_sp <= EMULATOR_END)
  2335.         {
  2336.           mthread->in_emulator = emulator_present;
  2337.           
  2338.           if (!all_mapped && cprocs)
  2339.         {
  2340.           usp = fetch_usp_from_emulator_stack (emul_sp);
  2341.           
  2342.           /* @@ Could be more accurate */
  2343.           if (! usp)
  2344.             error ("Zero stack pointer read from emulator?");
  2345.           
  2346.           /* Try to match this stack pointer to the cprocs that
  2347.            * don't yet have a kernel thread.
  2348.            */
  2349.           for (scan = cprocs; scan; scan = scan->next)
  2350.             {
  2351.               
  2352.               /* Check is this unmapped CPROC stack contains
  2353.                * the user stack pointer saved in the
  2354.                * emulator.
  2355.                */
  2356.               if (scan->reverse_map == -1 &&
  2357.               usp > scan->stack_base &&
  2358.               usp <= scan->stack_base + scan->stack_size)
  2359.             {
  2360.               mthread->cproc = scan;
  2361.               scan->reverse_map = index;
  2362.               break;
  2363.             }
  2364.             }
  2365.         }
  2366.         }
  2367.     }
  2368.     }
  2369. }
  2370.  
  2371. /*
  2372.  * Format of the thread_list command
  2373.  *
  2374.  *                  slot mid sel   name  emul ks susp  cstate wired   address
  2375.  */
  2376. #define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
  2377.  
  2378. #define TL_HEADER "\n@    MID  Name        KState CState   Where\n"
  2379.  
  2380. void
  2381. print_tl_address (stream, pc)
  2382.      GDB_FILE *stream;
  2383.      CORE_ADDR pc;
  2384. {
  2385.   if (! lookup_minimal_symbol_by_pc (pc))
  2386.     fprintf_filtered (stream, local_hex_format(), pc);
  2387.   else
  2388.     {
  2389.       extern int addressprint;
  2390.       extern int asm_demangle;
  2391.  
  2392.       int store    = addressprint;
  2393.       addressprint = 0;
  2394.       print_address_symbolic (pc, stream, asm_demangle, "");
  2395.       addressprint = store;
  2396.     }
  2397. }
  2398.  
  2399. /* For thread names, but also for gdb_message_port external name */
  2400. #define MAX_NAME_LEN 50
  2401.  
  2402. /* Returns the address of variable NAME or 0 if not found */
  2403. CORE_ADDR
  2404. lookup_address_of_variable (name)
  2405.      char *name;
  2406. {
  2407.   struct symbol *sym;
  2408.   CORE_ADDR symaddr = 0;
  2409.   struct minimal_symbol *msymbol;
  2410.  
  2411.   sym = lookup_symbol (name,
  2412.                (struct block *)NULL,
  2413.                VAR_NAMESPACE,
  2414.                (int *)NULL,
  2415.                (struct symtab **)NULL);
  2416.  
  2417.   if (sym)
  2418.     symaddr = SYMBOL_VALUE (sym);
  2419.  
  2420.   if (! symaddr)
  2421.     {
  2422.       msymbol = lookup_minimal_symbol (name, (struct objfile *) NULL);
  2423.  
  2424.       if (msymbol && msymbol->type == mst_data)
  2425.     symaddr = msymbol->address;
  2426.     }
  2427.  
  2428.   return symaddr;
  2429. }
  2430.  
  2431. static gdb_thread_t
  2432. get_cprocs()
  2433. {
  2434.   gdb_thread_t cproc_head;
  2435.   gdb_thread_t cproc_copy;
  2436.   CORE_ADDR their_cprocs;
  2437.   char *buf[TARGET_PTR_BIT / HOST_CHAR_BIT];
  2438.   char *name;
  2439.   cthread_t cthread;
  2440.   CORE_ADDR symaddr;
  2441.   
  2442.   symaddr = lookup_address_of_variable ("cproc_list");
  2443.  
  2444.   if (! symaddr)
  2445.     {
  2446.       /* cproc_list is not in a file compiled with debugging
  2447.      symbols, but don't give up yet */
  2448.  
  2449.       symaddr = lookup_address_of_variable ("cprocs");
  2450.  
  2451.       if (symaddr)
  2452.     {
  2453.       static int informed = 0;
  2454.       if (!informed)
  2455.         {
  2456.           informed++;
  2457.           warning ("Your program is loaded with an old threads library.");
  2458.           warning ("GDB does not know the old form of threads");
  2459.           warning ("so things may not work.");
  2460.         }
  2461.     }
  2462.     }
  2463.  
  2464.   /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
  2465.   if (! symaddr)
  2466.     return NULL;
  2467.  
  2468.   /* Get the address of the first cproc in the task */
  2469.   if (!mach3_read_inferior (symaddr,
  2470.                 buf,
  2471.                 TARGET_PTR_BIT / HOST_CHAR_BIT))
  2472.     error ("Can't read cproc master list at address (0x%x).", symaddr);
  2473.   their_cprocs = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
  2474.  
  2475.   /* Scan the CPROCs in the task.
  2476.      CPROCs are chained with LIST field, not NEXT field, which
  2477.      chains mutexes, condition variables and queues */
  2478.  
  2479.   cproc_head = NULL;
  2480.  
  2481.   while (their_cprocs != (CORE_ADDR)0)
  2482.     {
  2483.       CORE_ADDR cproc_copy_incarnation;
  2484.       cproc_copy = (gdb_thread_t) obstack_alloc (cproc_obstack,
  2485.                          sizeof (struct gdb_thread));
  2486.  
  2487.       if (!mach3_read_inferior (their_cprocs,
  2488.                 &cproc_copy.raw_cproc[0],
  2489.                 CPROC_SIZE))
  2490.     error("Can't read next cproc at 0x%x.", their_cprocs);
  2491.       cproc_copy = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
  2492.  
  2493.       their_cprocs =
  2494.     extract_address (cproc_copy.raw_cproc + CPROC_LIST_OFFSET,
  2495.              CPROC_LIST_SIZE);
  2496.       cproc_copy_incarnation =
  2497.     extract_address (cproc_copy.raw_cproc + CPROC_INCARNATION_OFFSET,
  2498.              CPROC_INCARNATION_SIZE);
  2499.  
  2500.       if (cproc_copy_incarnation == (CORE_ADDR)0)
  2501.     cproc_copy->cthread = NULL;
  2502.       else
  2503.     {
  2504.       /* This CPROC has an attached CTHREAD. Get its name */
  2505.       cthread = (cthread_t)obstack_alloc (cproc_obstack,
  2506.                           sizeof(struct cthread));
  2507.  
  2508.       if (!mach3_read_inferior (cproc_copy_incarnation,
  2509.                     cthread,
  2510.                     sizeof(struct cthread)))
  2511.         error("Can't read next thread at 0x%x.",
  2512.           cproc_copy_incarnation);
  2513.  
  2514.       cproc_copy->cthread = cthread;
  2515.  
  2516.       if (cthread->name)
  2517.         {
  2518.           name = (char *) obstack_alloc (cproc_obstack, MAX_NAME_LEN);
  2519.  
  2520.           if (!mach3_read_inferior(cthread->name, name, MAX_NAME_LEN))
  2521.         error("Can't read next thread's name at 0x%x.", cthread->name);
  2522.  
  2523.           cthread->name = name;
  2524.         }
  2525.     }
  2526.  
  2527.       /* insert in front */
  2528.       cproc_copy->next = cproc_head;
  2529.       cproc_head = cproc_copy;
  2530.     }
  2531.   return cproc_head;
  2532. }
  2533.  
  2534. #ifndef FETCH_CPROC_STATE
  2535. /*
  2536.  * Check if your machine does not grok the way this routine
  2537.  * fetches the FP,PC and SP of a cproc that is not
  2538.  * currently attached to any kernel thread (e.g. its cproc.context
  2539.  * field points to the place in stack where the context
  2540.  * is saved).
  2541.  *
  2542.  * If it doesn't, define your own routine.
  2543.  */
  2544. #define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
  2545.  
  2546. int
  2547. mach3_cproc_state (mthread)
  2548.      gdb_thread_t mthread;
  2549. {
  2550.   int context;
  2551.  
  2552.   if (! mthread || !mthread->cproc || !mthread->cproc->context)
  2553.     return -1;
  2554.  
  2555.   context = extract_signed_integer
  2556.     (mthread->cproc->raw_cproc + CPROC_CONTEXT_OFFSET,
  2557.      CPROC_CONTEXT_SIZE);
  2558.  
  2559.   mthread->sp = context + MACHINE_CPROC_SP_OFFSET;
  2560.  
  2561.   if (mach3_read_inferior (context + MACHINE_CPROC_PC_OFFSET,
  2562.                &mthread->pc,
  2563.                sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
  2564.     {
  2565.       warning ("Can't read cproc pc from inferior");
  2566.       return -1;
  2567.     }
  2568.  
  2569.   if (mach3_read_inferior (context + MACHINE_CPROC_FP_OFFSET,
  2570.                &mthread->fp,
  2571.                sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
  2572.     {
  2573.       warning ("Can't read cproc fp from inferior");
  2574.       return -1;
  2575.     }
  2576.  
  2577.   return 0;
  2578. }
  2579. #endif /* FETCH_CPROC_STATE */
  2580.  
  2581.  
  2582. void
  2583. thread_list_command()
  2584. {
  2585.   thread_basic_info_data_t ths;
  2586.   int     thread_count;
  2587.   gdb_thread_t cprocs;
  2588.   gdb_thread_t scan;
  2589.   int     index;
  2590.   char   *name;
  2591.   char    selected;
  2592.   char   *wired;
  2593.   int     infoCnt;
  2594.   kern_return_t ret;
  2595.   mach_port_t   mid_or_port;
  2596.   gdb_thread_t  their_threads;
  2597.   gdb_thread_t  kthread;
  2598.  
  2599.   int neworder = 1;
  2600.  
  2601.   char *fmt = "There are %d kernel threads in task %d.\n";
  2602.   
  2603.   int tmid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
  2604.   
  2605.   MACH_ERROR_NO_INFERIOR;
  2606.   
  2607.   thread_count = fetch_thread_info (inferior_task,
  2608.                     &their_threads);
  2609.   if (thread_count == -1)
  2610.     return;
  2611.   
  2612.   if (thread_count == 1)
  2613.     fmt = "There is %d kernel thread in task %d.\n";
  2614.   
  2615.   printf_filtered (fmt, thread_count, tmid);
  2616.   
  2617.   puts_filtered (TL_HEADER);
  2618.   
  2619.   cprocs = get_cprocs();
  2620.   
  2621.   map_cprocs_to_kernel_threads (cprocs, their_threads, thread_count);
  2622.   
  2623.   for (scan = cprocs; scan; scan = scan->next)
  2624.     {
  2625.       int mid;
  2626.       char buf[10];
  2627.       char slot[3];
  2628.       
  2629.       selected = ' ';
  2630.       
  2631.       /* a wired cproc? */
  2632.       wired = (extract_address (scan->raw_cproc + CPROC_WIRED_OFFSET,
  2633.                 CPROC_WIRED_SIZE)
  2634.            ? "wired" : "");
  2635.  
  2636.       if (scan->reverse_map != -1)
  2637.     kthread  = (their_threads + scan->reverse_map);
  2638.       else
  2639.     kthread  = NULL;
  2640.  
  2641.       if (kthread)
  2642.     {
  2643.       /* These cprocs have a kernel thread */
  2644.       
  2645.       mid = map_port_name_to_mid (kthread->name, MACH_TYPE_THREAD);
  2646.       
  2647.       infoCnt = THREAD_BASIC_INFO_COUNT;
  2648.       
  2649.       ret = thread_info (kthread->name,
  2650.                  THREAD_BASIC_INFO,
  2651.                  (thread_info_t)&ths,
  2652.                  &infoCnt);
  2653.       
  2654.       if (ret != KERN_SUCCESS)
  2655.         {
  2656.           warning ("Unable to get basic info on thread %d : %s",
  2657.                mid,
  2658.                mach_error_string (ret));
  2659.           continue;
  2660.         }
  2661.  
  2662.       /* Who is the first to have more than 100 threads */
  2663.       sprintf (slot, "%d", kthread->slotid%100);
  2664.  
  2665.       if (kthread->name == current_thread)
  2666.         selected = '*';
  2667.       
  2668.       if (ths.suspend_count)
  2669.         sprintf (buf, "%d", ths.suspend_count);
  2670.       else
  2671.         buf[0] = '\000';
  2672.  
  2673. #if 0
  2674.       if (ths.flags & TH_FLAGS_SWAPPED)
  2675.         strcat (buf, "S");
  2676. #endif
  2677.  
  2678.       if (ths.flags & TH_FLAGS_IDLE)
  2679.         strcat (buf, "I");
  2680.  
  2681.       /* FIXME: May run afloul of arbitrary limit in printf_filtered.  */
  2682.       printf_filtered (TL_FORMAT,
  2683.                slot,
  2684.                mid,
  2685.                selected,
  2686.                get_thread_name (scan, kthread->slotid),
  2687.                kthread->in_emulator ? "E" : "",
  2688.                translate_state (ths.run_state),
  2689.                buf,
  2690.                translate_cstate (scan->state),
  2691.                wired);
  2692.       print_tl_address (gdb_stdout, kthread->pc);
  2693.     }
  2694.       else
  2695.     {
  2696.       /* These cprocs don't have a kernel thread.
  2697.        * find out the calling frame with 
  2698.        * FETCH_CPROC_STATE.
  2699.        */
  2700.  
  2701.       struct gdb_thread state;
  2702.  
  2703. #if 0
  2704.       /* jtv -> emcmanus: why do you want this here? */
  2705.       if (scan->incarnation == NULL)
  2706.         continue; /* EMcM */
  2707. #endif
  2708.  
  2709.       /* FIXME: May run afloul of arbitrary limit in printf_filtered.  */
  2710.       printf_filtered (TL_FORMAT,
  2711.                "-",
  2712.                -neworder,    /* Pseudo MID */
  2713.                selected,
  2714.                get_thread_name (scan, -neworder),
  2715.                "",
  2716.                "-",    /* kernel state */
  2717.                "",
  2718.                translate_cstate (scan->state),
  2719.                "");
  2720.       state.cproc = scan;
  2721.  
  2722.       if (FETCH_CPROC_STATE (&state) == -1)
  2723.         puts_filtered ("???");
  2724.       else
  2725.         print_tl_address (gdb_stdout, state.pc);
  2726.  
  2727.       neworder++;
  2728.     }
  2729.       puts_filtered ("\n");
  2730.     }
  2731.   
  2732.   /* Scan for kernel threads without cprocs */
  2733.   for (index = 0; index < thread_count; index++)
  2734.     {
  2735.       if (! their_threads[index].cproc)
  2736.     {
  2737.       int mid;
  2738.       
  2739.       char buf[10];
  2740.       char slot[3];
  2741.  
  2742.       mach_port_t name = their_threads[index].name;
  2743.       
  2744.       mid = map_port_name_to_mid (name, MACH_TYPE_THREAD);
  2745.       
  2746.       infoCnt = THREAD_BASIC_INFO_COUNT;
  2747.       
  2748.       ret = thread_info(name,
  2749.                 THREAD_BASIC_INFO,
  2750.                 (thread_info_t)&ths,
  2751.                 &infoCnt);
  2752.         
  2753.       if (ret != KERN_SUCCESS)
  2754.         {
  2755.           warning ("Unable to get basic info on thread %d : %s",
  2756.                mid,
  2757.                mach_error_string (ret));
  2758.           continue;
  2759.         }
  2760.  
  2761.       sprintf (slot, "%d", index%100);
  2762.  
  2763.       if (name == current_thread)
  2764.         selected = '*';
  2765.       else
  2766.         selected = ' ';
  2767.  
  2768.       if (ths.suspend_count)
  2769.         sprintf (buf, "%d", ths.suspend_count);
  2770.       else
  2771.         buf[0] = '\000';
  2772.  
  2773. #if 0
  2774.       if (ths.flags & TH_FLAGS_SWAPPED)
  2775.         strcat (buf, "S");
  2776. #endif
  2777.  
  2778.       if (ths.flags & TH_FLAGS_IDLE)
  2779.         strcat (buf, "I");
  2780.  
  2781.       /* FIXME: May run afloul of arbitrary limit in printf_filtered.  */
  2782.       printf_filtered (TL_FORMAT,
  2783.                slot,
  2784.                mid,
  2785.                selected,
  2786.                get_thread_name (NULL, index),
  2787.                their_threads[index].in_emulator ? "E" : "",
  2788.                translate_state (ths.run_state),
  2789.                buf,
  2790.                "",   /* No cproc state */
  2791.                "");    /* Can't be wired */
  2792.       print_tl_address (gdb_stdout, their_threads[index].pc);
  2793.       puts_filtered ("\n");
  2794.     }
  2795.     }
  2796.   
  2797.   obstack_free (cproc_obstack, 0);
  2798.   obstack_init (cproc_obstack);
  2799. }
  2800.  
  2801. void
  2802. thread_select_command(args, from_tty)
  2803.      char *args;
  2804.      int from_tty;
  2805. {
  2806.   int mid;
  2807.   thread_array_t thread_list;
  2808.   int thread_count;
  2809.   kern_return_t ret;
  2810.   int is_slot = 0;
  2811.  
  2812.   MACH_ERROR_NO_INFERIOR;
  2813.  
  2814.   if (!args)
  2815.     error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
  2816.  
  2817.   while (*args == ' ' || *args == '\t')
  2818.     args++;
  2819.  
  2820.   if (*args == '@')
  2821.     {
  2822.       is_slot++;
  2823.       args++;
  2824.     }
  2825.  
  2826.   mid = atoi(args);
  2827.  
  2828.   if (mid == 0)
  2829.     if (!is_slot || *args != '0') /* Rudimentary checks */
  2830.       error ("You must select threads by MID or @SLOTNUMBER");
  2831.  
  2832.   if (select_thread (inferior_task, mid, is_slot?2:1) != KERN_SUCCESS)
  2833.     return;
  2834.  
  2835.   if (from_tty)
  2836.     printf_filtered ("Thread %d selected\n",
  2837.              is_slot ? map_port_name_to_mid (current_thread,
  2838.                              MACH_TYPE_THREAD) : mid);
  2839. }
  2840.  
  2841. thread_trace (thread, set)
  2842. mach_port_t thread;
  2843. boolean_t   set;
  2844. {
  2845.   int            flavor   = TRACE_FLAVOR;
  2846.   unsigned int        stateCnt = TRACE_FLAVOR_SIZE;
  2847.   kern_return_t        ret;
  2848.   thread_state_data_t    state;
  2849.  
  2850.   if (! MACH_PORT_VALID (thread))
  2851.     {
  2852.       warning ("thread_trace: invalid thread");
  2853.       return;
  2854.     }
  2855.  
  2856.   if (must_suspend_thread)
  2857.     setup_thread (thread, 1);
  2858.  
  2859.   ret = thread_get_state(thread, flavor, state, &stateCnt);
  2860.   CHK ("thread_trace: error reading thread state", ret);
  2861.   
  2862.   if (set)
  2863.     {
  2864.       TRACE_SET (thread, state);
  2865.     }
  2866.   else
  2867.     {
  2868.       if (! TRACE_CLEAR (thread, state))
  2869.     {
  2870.       if (must_suspend_thread)
  2871.         setup_thread (thread, 0);
  2872.       return;
  2873.     }
  2874.     }
  2875.  
  2876.   ret = thread_set_state(thread, flavor, state, stateCnt);
  2877.   CHK ("thread_trace: error writing thread state", ret);
  2878.   if (must_suspend_thread)
  2879.     setup_thread (thread, 0);
  2880. }  
  2881.  
  2882. #ifdef    FLUSH_INFERIOR_CACHE
  2883.  
  2884. /* When over-writing code on some machines the I-Cache must be flushed
  2885.    explicitly, because it is not kept coherent by the lazy hardware.
  2886.    This definitely includes breakpoints, for instance, or else we
  2887.    end up looping in mysterious Bpt traps */
  2888.  
  2889. flush_inferior_icache(pc, amount)
  2890.      CORE_ADDR pc;
  2891. {
  2892.   vm_machine_attribute_val_t flush = MATTR_VAL_ICACHE_FLUSH;
  2893.   kern_return_t   ret;
  2894.   
  2895.   ret = vm_machine_attribute (inferior_task,
  2896.                   pc,
  2897.                   amount,
  2898.                   MATTR_CACHE,
  2899.                   &flush);
  2900.   if (ret != KERN_SUCCESS)
  2901.     warning ("Error flushing inferior's cache : %s",
  2902.          mach_error_string (ret));
  2903. }
  2904. #endif    FLUSH_INFERIOR_CACHE
  2905.  
  2906.  
  2907. static
  2908. suspend_all_threads (from_tty)
  2909.      int from_tty;
  2910. {
  2911.   kern_return_t       ret;
  2912.   thread_array_t   thread_list;
  2913.   int           thread_count, index;
  2914.   int           infoCnt;
  2915.   thread_basic_info_data_t th_info;
  2916.  
  2917.   
  2918.   ret = task_threads (inferior_task, &thread_list, &thread_count);
  2919.   if (ret != KERN_SUCCESS)
  2920.     {
  2921.       warning ("Could not suspend inferior threads.");
  2922.       kill_inferior ();
  2923.       return_to_top_level ();
  2924.     }
  2925.   
  2926.   for (index = 0; index < thread_count; index++)
  2927.     {
  2928.       int mid;
  2929.  
  2930.       mid = map_port_name_to_mid (thread_list[ index ],
  2931.                   MACH_TYPE_THREAD);
  2932.       
  2933.       ret = thread_suspend(thread_list[ index ]);
  2934.  
  2935.       if (ret != KERN_SUCCESS)
  2936.     warning ("Error trying to suspend thread %d : %s",
  2937.          mid, mach_error_string (ret));
  2938.  
  2939.       if (from_tty)
  2940.     {
  2941.       infoCnt = THREAD_BASIC_INFO_COUNT;
  2942.       ret = thread_info (thread_list[ index ],
  2943.                  THREAD_BASIC_INFO,
  2944.                  (thread_info_t) &th_info,
  2945.                  &infoCnt);
  2946.       CHK ("suspend can't get thread info", ret);
  2947.       
  2948.       warning ("Thread %d suspend count is %d",
  2949.            mid, th_info.suspend_count);
  2950.     }
  2951.     }
  2952.  
  2953.   consume_send_rights (thread_list, thread_count);
  2954.   ret = vm_deallocate(mach_task_self(),
  2955.               (vm_address_t)thread_list, 
  2956.               (thread_count * sizeof(int)));
  2957.   CHK ("Error trying to deallocate thread list", ret);
  2958. }
  2959.  
  2960. void
  2961. thread_suspend_command (args, from_tty)
  2962.      char *args;
  2963.      int from_tty;
  2964. {
  2965.   kern_return_t ret;
  2966.   int           mid;
  2967.   mach_port_t   saved_thread;
  2968.   int           infoCnt;
  2969.   thread_basic_info_data_t th_info;
  2970.   
  2971.   MACH_ERROR_NO_INFERIOR;
  2972.  
  2973.   if (!strcasecmp (args, "all")) {
  2974.     suspend_all_threads (from_tty);
  2975.     return;
  2976.   }
  2977.  
  2978.   saved_thread = current_thread;
  2979.  
  2980.   mid = parse_thread_id (args, 0, 0);
  2981.  
  2982.   if (mid < 0)
  2983.     error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
  2984.  
  2985.   if (mid == 0)
  2986.     mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
  2987.   else
  2988.     if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
  2989.       {
  2990.     if (current_thread)
  2991.       current_thread = saved_thread;
  2992.     error ("Could not select thread %d", mid);
  2993.       }
  2994.  
  2995.   ret = thread_suspend (current_thread);
  2996.   if (ret != KERN_SUCCESS)
  2997.     warning ("thread_suspend failed : %s",
  2998.          mach_error_string (ret));
  2999.  
  3000.   infoCnt = THREAD_BASIC_INFO_COUNT;
  3001.   ret = thread_info (current_thread,
  3002.              THREAD_BASIC_INFO,
  3003.              (thread_info_t) &th_info,
  3004.              &infoCnt);
  3005.   CHK ("suspend can't get thread info", ret);
  3006.   
  3007.   warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
  3008.   
  3009.   current_thread = saved_thread;
  3010. }
  3011.  
  3012. resume_all_threads (from_tty)
  3013.      int from_tty;
  3014. {
  3015.     kern_return_t  ret;
  3016.     thread_array_t thread_list;
  3017.     int           thread_count, index;
  3018.     int            mid;
  3019.     int           infoCnt;
  3020.     thread_basic_info_data_t th_info;
  3021.  
  3022.     ret = task_threads (inferior_task, &thread_list, &thread_count);
  3023.     if (ret != KERN_SUCCESS)
  3024.       {
  3025.     kill_inferior ();
  3026.     error("task_threads", mach_error_string( ret));
  3027.       }
  3028.  
  3029.     for (index = 0; index < thread_count; index++)
  3030.       {
  3031.     infoCnt = THREAD_BASIC_INFO_COUNT;
  3032.     ret = thread_info (thread_list [ index ],
  3033.                THREAD_BASIC_INFO,
  3034.                (thread_info_t) &th_info,
  3035.                &infoCnt);
  3036.     CHK ("resume_all can't get thread info", ret);
  3037.     
  3038.     mid = map_port_name_to_mid (thread_list[ index ],
  3039.                     MACH_TYPE_THREAD);
  3040.     
  3041.     if (! th_info.suspend_count)
  3042.       {
  3043.         if (mid != -1 && from_tty)
  3044.           warning ("Thread %d is not suspended", mid);
  3045.         continue;
  3046.       }
  3047.  
  3048.     ret = thread_resume (thread_list[ index ]);
  3049.  
  3050.     if (ret != KERN_SUCCESS)
  3051.       warning ("Error trying to resume thread %d : %s",
  3052.            mid, mach_error_string (ret));
  3053.     else if (mid != -1 && from_tty)
  3054.       warning ("Thread %d suspend count is %d",
  3055.            mid, --th_info.suspend_count);
  3056.       }
  3057.  
  3058.     consume_send_rights (thread_list, thread_count);
  3059.     ret = vm_deallocate(mach_task_self(),
  3060.             (vm_address_t)thread_list, 
  3061.             (thread_count * sizeof(int)));
  3062.     CHK("Error trying to deallocate thread list", ret);
  3063. }
  3064.  
  3065. void
  3066. thread_resume_command (args, from_tty)
  3067.      char *args;
  3068.      int from_tty;
  3069. {
  3070.   int mid;
  3071.   mach_port_t saved_thread;
  3072.   kern_return_t ret;
  3073.   thread_basic_info_data_t th_info;
  3074.   int infoCnt = THREAD_BASIC_INFO_COUNT;
  3075.   
  3076.   MACH_ERROR_NO_INFERIOR;
  3077.  
  3078.   if (!strcasecmp (args, "all")) {
  3079.     resume_all_threads (from_tty);
  3080.     return;
  3081.   }
  3082.  
  3083.   saved_thread = current_thread;
  3084.  
  3085.   mid = parse_thread_id (args, 0, 0);
  3086.  
  3087.   if (mid < 0)
  3088.     error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
  3089.  
  3090.   if (mid == 0)
  3091.     mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
  3092.   else
  3093.     if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
  3094.       {
  3095.     if (current_thread)
  3096.       current_thread = saved_thread;
  3097.     return_to_top_level ();
  3098.       }
  3099.  
  3100.   ret = thread_info (current_thread,
  3101.              THREAD_BASIC_INFO,
  3102.              (thread_info_t) &th_info,
  3103.              &infoCnt);
  3104.   CHK ("resume can't get thread info", ret);
  3105.   
  3106.   if (! th_info.suspend_count)
  3107.     {
  3108.       warning ("Thread %d is not suspended", mid);
  3109.       goto out;
  3110.     }
  3111.  
  3112.   ret = thread_resume (current_thread);
  3113.   if (ret != KERN_SUCCESS)
  3114.     warning ("thread_resume failed : %s",
  3115.          mach_error_string (ret));
  3116.   else
  3117.     {
  3118.       th_info.suspend_count--;
  3119.       warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
  3120.     }
  3121.       
  3122.  out:
  3123.   current_thread = saved_thread;
  3124. }
  3125.  
  3126. void
  3127. thread_kill_command (args, from_tty)
  3128.      char *args;
  3129.      int from_tty;
  3130. {
  3131.   int mid;
  3132.   kern_return_t ret;
  3133.   int thread_count;
  3134.   thread_array_t thread_table;
  3135.   int   index;
  3136.   mach_port_t thread_to_kill = MACH_PORT_NULL;
  3137.   
  3138.   
  3139.   MACH_ERROR_NO_INFERIOR;
  3140.  
  3141.   if (!args)
  3142.     error_no_arg ("thread mid to kill from the inferior task");
  3143.  
  3144.   mid = parse_thread_id (args, 0, 0);
  3145.  
  3146.   if (mid < 0)
  3147.     error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
  3148.  
  3149.   if (mid)
  3150.     {
  3151.       ret = machid_mach_port (mid_server, mid_auth, mid, &thread_to_kill);
  3152.       CHK ("thread_kill_command: machid_mach_port map failed", ret);
  3153.     }
  3154.   else
  3155.     mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
  3156.       
  3157.   /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
  3158.   ret = task_threads (inferior_task, &thread_table, &thread_count);
  3159.   CHK ("Error getting inferior's thread list", ret);
  3160.   
  3161.   if (thread_to_kill == current_thread)
  3162.     {
  3163.       ret = thread_terminate (thread_to_kill);
  3164.       CHK ("Thread could not be terminated", ret);
  3165.  
  3166.       if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
  3167.     warning ("Last thread was killed, use \"kill\" command to kill task");
  3168.     }
  3169.   else
  3170.     for (index = 0; index < thread_count; index++)
  3171.       if (thread_table [ index ] == thread_to_kill)
  3172.     {
  3173.       ret = thread_terminate (thread_to_kill);
  3174.       CHK ("Thread could not be terminated", ret);
  3175.     }
  3176.  
  3177.   if (thread_count > 1)
  3178.     consume_send_rights (thread_table, thread_count);
  3179.   
  3180.   ret = vm_deallocate (mach_task_self(), (vm_address_t)thread_table, 
  3181.                (thread_count * sizeof(mach_port_t)));
  3182.   CHK ("Error trying to deallocate thread list", ret);
  3183.   
  3184.   warning ("Thread %d killed", mid);
  3185. }
  3186.  
  3187.  
  3188. /* Task specific commands; add more if you like */
  3189.  
  3190. void
  3191. task_resume_command (args, from_tty)
  3192.      char *args;
  3193.      int from_tty;
  3194. {
  3195.   kern_return_t ret;
  3196.   task_basic_info_data_t ta_info;
  3197.   int infoCnt = TASK_BASIC_INFO_COUNT;
  3198.   int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
  3199.   
  3200.   MACH_ERROR_NO_INFERIOR;
  3201.  
  3202.   /* Would be trivial to change, but is it desirable? */
  3203.   if (args)
  3204.     error ("Currently gdb can resume only it's inferior task");
  3205.  
  3206.   ret = task_info (inferior_task,
  3207.            TASK_BASIC_INFO,
  3208.            (task_info_t) &ta_info,
  3209.            &infoCnt);
  3210.   CHK ("task_resume_command: task_info failed", ret);
  3211.   
  3212.   if (ta_info.suspend_count == 0)
  3213.     error ("Inferior task %d is not suspended", mid);
  3214.   else if (ta_info.suspend_count == 1 &&
  3215.        from_tty &&
  3216.        !query ("Suspend count is now 1. Do you know what you are doing? "))
  3217.     error ("Task not resumed");
  3218.  
  3219.   ret = task_resume (inferior_task);
  3220.   CHK ("task_resume_command: task_resume", ret);
  3221.  
  3222.   if (ta_info.suspend_count == 1)
  3223.     {
  3224.       warning ("Inferior task %d is no longer suspended", mid);
  3225.       must_suspend_thread = 1;
  3226.       /* @@ This is not complete: Registers change all the time when not
  3227.      suspended! */
  3228.       registers_changed ();
  3229.     }
  3230.   else
  3231.     warning ("Inferior task %d suspend count is now %d",
  3232.          mid, ta_info.suspend_count-1);
  3233. }
  3234.  
  3235.  
  3236. void
  3237. task_suspend_command (args, from_tty)
  3238.      char *args;
  3239.      int from_tty;
  3240. {
  3241.   kern_return_t ret;
  3242.   task_basic_info_data_t ta_info;
  3243.   int infoCnt = TASK_BASIC_INFO_COUNT;
  3244.   int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
  3245.   
  3246.   MACH_ERROR_NO_INFERIOR;
  3247.  
  3248.   /* Would be trivial to change, but is it desirable? */
  3249.   if (args)
  3250.     error ("Currently gdb can suspend only it's inferior task");
  3251.  
  3252.   ret = task_suspend (inferior_task);
  3253.   CHK ("task_suspend_command: task_suspend", ret);
  3254.  
  3255.   must_suspend_thread = 0;
  3256.  
  3257.   ret = task_info (inferior_task,
  3258.            TASK_BASIC_INFO,
  3259.            (task_info_t) &ta_info,
  3260.            &infoCnt);
  3261.   CHK ("task_suspend_command: task_info failed", ret);
  3262.   
  3263.   warning ("Inferior task %d suspend count is now %d",
  3264.        mid, ta_info.suspend_count);
  3265. }
  3266.  
  3267. static char *
  3268. get_size (bytes)
  3269.      int bytes;
  3270. {
  3271.   static char size [ 30 ];
  3272.   int zz = bytes/1024;
  3273.  
  3274.   if (zz / 1024)
  3275.     sprintf (size, "%-2.1f M", ((float)bytes)/(1024.0*1024.0));
  3276.   else
  3277.     sprintf (size, "%d K", zz);
  3278.  
  3279.   return size;
  3280. }
  3281.  
  3282. /* Does this require the target task to be suspended?? I don't think so. */
  3283. void
  3284. task_info_command (args, from_tty)
  3285.      char *args;
  3286.      int from_tty;
  3287. {
  3288.   int mid = -5;
  3289.   mach_port_t task;
  3290.   kern_return_t ret;
  3291.   task_basic_info_data_t ta_info;
  3292.   int infoCnt = TASK_BASIC_INFO_COUNT;
  3293.   int page_size = round_page(1);
  3294.   int thread_count = 0;
  3295.   
  3296.   if (MACH_PORT_VALID (inferior_task))
  3297.     mid = map_port_name_to_mid (inferior_task,
  3298.                 MACH_TYPE_TASK);
  3299.  
  3300.   task = inferior_task;
  3301.  
  3302.   if (args)
  3303.     {
  3304.       int tmid = atoi (args);
  3305.  
  3306.       if (tmid <= 0)
  3307.     error ("Invalid mid %d for task info", tmid);
  3308.  
  3309.       if (tmid != mid)
  3310.     {
  3311.       mid = tmid;
  3312.       ret = machid_mach_port (mid_server, mid_auth, tmid, &task);
  3313.       CHK ("task_info_command: machid_mach_port map failed", ret);
  3314.     }
  3315.     }
  3316.  
  3317.   if (mid < 0)
  3318.     error ("You have to give the task MID as an argument");
  3319.  
  3320.   ret = task_info (task,
  3321.            TASK_BASIC_INFO,
  3322.            (task_info_t) &ta_info,
  3323.            &infoCnt);
  3324.   CHK ("task_info_command: task_info failed", ret);
  3325.  
  3326.   printf_filtered ("\nTask info for task %d:\n\n", mid);
  3327.   printf_filtered (" Suspend count : %d\n", ta_info.suspend_count);
  3328.   printf_filtered (" Base priority : %d\n", ta_info.base_priority);
  3329.   printf_filtered (" Virtual size  : %s\n", get_size (ta_info.virtual_size));
  3330.   printf_filtered (" Resident size : %s\n", get_size (ta_info.resident_size));
  3331.  
  3332.   {
  3333.     thread_array_t thread_list;
  3334.     
  3335.     ret = task_threads (task, &thread_list, &thread_count);
  3336.     CHK ("task_info_command: task_threads", ret);
  3337.     
  3338.     printf_filtered (" Thread count  : %d\n", thread_count);
  3339.  
  3340.     consume_send_rights (thread_list, thread_count);
  3341.     ret = vm_deallocate(mach_task_self(),
  3342.             (vm_address_t)thread_list, 
  3343.             (thread_count * sizeof(int)));
  3344.     CHK("Error trying to deallocate thread list", ret);
  3345.   }
  3346.   if (have_emulator_p (task))
  3347.     printf_filtered (" Emulator at   : 0x%x..0x%x\n",
  3348.              EMULATOR_BASE, EMULATOR_END);
  3349.   else
  3350.     printf_filtered (" No emulator.\n");
  3351.  
  3352.   if (thread_count && task == inferior_task)
  3353.     printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
  3354. }
  3355.  
  3356. /* You may either FORWARD the exception to the inferior, or KEEP
  3357.  * it and return to GDB command level.
  3358.  *
  3359.  * exception mid [ forward | keep ]
  3360.  */
  3361.  
  3362. static void
  3363. exception_command (args, from_tty)
  3364.      char *args;
  3365.      int from_tty;
  3366. {
  3367.   char *scan = args;
  3368.   int exception;
  3369.   int len;
  3370.  
  3371.   if (!args)
  3372.     error_no_arg ("exception number action");
  3373.  
  3374.   while (*scan == ' ' || *scan == '\t') scan++;
  3375.   
  3376.   if ('0' <= *scan && *scan <= '9')
  3377.     while ('0' <= *scan && *scan <= '9')
  3378.       scan++;
  3379.   else
  3380.     error ("exception number action");
  3381.  
  3382.   exception = atoi (args);
  3383.   if (exception <= 0 || exception > MAX_EXCEPTION)
  3384.     error ("Allowed exception numbers are in range 1..%d",
  3385.        MAX_EXCEPTION);
  3386.  
  3387.   if (*scan != ' ' && *scan != '\t')
  3388.     error ("exception number must be followed by a space");
  3389.   else
  3390.     while (*scan == ' ' || *scan == '\t') scan++;
  3391.  
  3392.   args = scan;
  3393.   len = 0;
  3394.   while (*scan)
  3395.     {
  3396.       len++;
  3397.       scan++;
  3398.     }
  3399.  
  3400.   if (!len)
  3401.     error("exception number action");
  3402.  
  3403.   if (!strncasecmp (args, "forward", len))
  3404.     exception_map[ exception ].forward = TRUE;
  3405.   else if (!strncasecmp (args, "keep", len))
  3406.     exception_map[ exception ].forward = FALSE;
  3407.   else
  3408.     error ("exception action is either \"keep\" or \"forward\"");
  3409. }
  3410.  
  3411. static void
  3412. print_exception_info (exception)
  3413.      int exception;
  3414. {
  3415.   boolean_t forward = exception_map[ exception ].forward;
  3416.  
  3417.   printf_filtered ("%s\t(%d): ", exception_map[ exception ].name,
  3418.            exception);
  3419.   if (!forward)
  3420.     if (exception_map[ exception ].sigmap != SIG_UNKNOWN)
  3421.       printf_filtered ("keep and handle as signal %d\n",
  3422.                exception_map[ exception ].sigmap);
  3423.     else
  3424.       printf_filtered ("keep and handle as unknown signal %d\n",
  3425.                exception_map[ exception ].sigmap);
  3426.   else
  3427.     printf_filtered ("forward exception to inferior\n");
  3428. }
  3429.  
  3430. void
  3431. exception_info (args, from_tty)
  3432.      char *args;
  3433.      int from_tty;
  3434. {
  3435.   int exception;
  3436.  
  3437.   if (!args)
  3438.     for (exception = 1; exception <= MAX_EXCEPTION; exception++)
  3439.       print_exception_info (exception);
  3440.   else
  3441.     {
  3442.       exception = atoi (args);
  3443.  
  3444.       if (exception <= 0 || exception > MAX_EXCEPTION)
  3445.     error ("Invalid exception number, values from 1 to %d allowed",
  3446.            MAX_EXCEPTION);
  3447.       print_exception_info (exception);
  3448.     }
  3449. }
  3450.  
  3451. /* Check for actions for mach exceptions.
  3452.  */
  3453. mach3_exception_actions (w, force_print_only, who)
  3454.      WAITTYPE *w;
  3455.      boolean_t force_print_only;
  3456.      char *who;
  3457. {
  3458.   boolean_t force_print = FALSE;
  3459.  
  3460.   
  3461.   if (force_print_only ||
  3462.       exception_map[stop_exception].sigmap == SIG_UNKNOWN)
  3463.     force_print = TRUE;
  3464.   else
  3465.     WSETSTOP (*w, exception_map[stop_exception].sigmap);
  3466.  
  3467.   if (exception_map[stop_exception].print || force_print)
  3468.     {
  3469.       int giveback = grab_terminal ();
  3470.       
  3471.       printf_filtered ("\n%s received %s exception : ",
  3472.                who,
  3473.                exception_map[stop_exception].name);
  3474.       
  3475.       wrap_here ("   ");
  3476.  
  3477.       switch(stop_exception) {
  3478.       case EXC_BAD_ACCESS:
  3479.     printf_filtered ("referencing address 0x%x : %s\n",
  3480.              stop_subcode,
  3481.              mach_error_string (stop_code));
  3482.     break;
  3483.       case EXC_BAD_INSTRUCTION:
  3484.     printf_filtered
  3485.       ("illegal or undefined instruction. code %d subcode %d\n",
  3486.        stop_code, stop_subcode);
  3487.     break;
  3488.       case EXC_ARITHMETIC:
  3489.     printf_filtered ("code %d\n", stop_code);
  3490.     break;
  3491.       case EXC_EMULATION:
  3492.     printf_filtered ("code %d subcode %d\n", stop_code, stop_subcode);
  3493.     break;
  3494.       case EXC_SOFTWARE:
  3495.     printf_filtered ("%s specific, code 0x%x\n",
  3496.              stop_code < 0xffff ? "hardware" : "os emulation",
  3497.              stop_code);
  3498.     break;
  3499.       case EXC_BREAKPOINT:
  3500.     printf_filtered ("type %d (machine dependent)\n",
  3501.              stop_code);
  3502.     break;
  3503.       default:
  3504.     fatal ("Unknown exception");
  3505.       }
  3506.       
  3507.       if (giveback)
  3508.     terminal_inferior ();
  3509.     }
  3510. }
  3511.  
  3512. setup_notify_port (create_new)
  3513.      int create_new;
  3514. {
  3515.   kern_return_t ret;
  3516.  
  3517.   if (MACH_PORT_VALID (our_notify_port))
  3518.     {
  3519.       ret = mach_port_destroy (mach_task_self (), our_notify_port);
  3520.       CHK ("Could not destroy our_notify_port", ret);
  3521.     }
  3522.  
  3523.   our_notify_port = MACH_PORT_NULL;
  3524.   notify_chain    = (port_chain_t) NULL;
  3525.   port_chain_destroy (port_chain_obstack);
  3526.  
  3527.   if (create_new)
  3528.     {
  3529.       ret = mach_port_allocate (mach_task_self(),
  3530.                 MACH_PORT_RIGHT_RECEIVE,
  3531.                 &our_notify_port);
  3532.       if (ret != KERN_SUCCESS)
  3533.     fatal("Creating notify port %s", mach_error_string(ret));
  3534.       
  3535.       ret = mach_port_move_member(mach_task_self(), 
  3536.                   our_notify_port,
  3537.                   inferior_wait_port_set);
  3538.       if (ret != KERN_SUCCESS)
  3539.     fatal("initial move member %s",mach_error_string(ret));
  3540.     }
  3541. }
  3542.  
  3543. /*
  3544.  * Register our message port to the net name server
  3545.  *
  3546.  * Currently used only by the external stop-gdb program
  3547.  * since ^C does not work if you would like to enter
  3548.  * gdb command level while debugging your program.
  3549.  *
  3550.  * NOTE: If the message port is sometimes used for other
  3551.  * purposes also, the NAME must not be a guessable one.
  3552.  * Then, there should be a way to change it.
  3553.  */
  3554.  
  3555. char registered_name[ MAX_NAME_LEN ];
  3556.  
  3557. void
  3558. message_port_info (args, from_tty)
  3559.      char *args;
  3560.      int from_tty;
  3561. {
  3562.   if (registered_name[0])
  3563.     printf_filtered ("gdb's message port name: '%s'\n",
  3564.              registered_name);
  3565.   else
  3566.     printf_filtered ("gdb's message port is not currently registered\n");
  3567. }
  3568.  
  3569. void
  3570. gdb_register_port (name, port)
  3571.      char *name;
  3572.      mach_port_t port;
  3573. {
  3574.   kern_return_t ret;
  3575.   static int already_signed = 0;
  3576.   int len;
  3577.  
  3578.   if (! MACH_PORT_VALID (port) || !name || !*name)
  3579.     {
  3580.       warning ("Invalid registration request");
  3581.       return;
  3582.     }
  3583.  
  3584.   if (! already_signed)
  3585.     {
  3586.       ret = mach_port_insert_right (mach_task_self (),
  3587.                     our_message_port,
  3588.                     our_message_port,
  3589.                     MACH_MSG_TYPE_MAKE_SEND);
  3590.       CHK ("Failed to create a signature to our_message_port", ret);
  3591.       already_signed = 1;
  3592.     }
  3593.   else if (already_signed > 1)
  3594.     {
  3595.       ret = netname_check_out (name_server_port,
  3596.                    registered_name,
  3597.                    our_message_port);
  3598.       CHK ("Failed to check out gdb's message port", ret);
  3599.       registered_name[0] = '\000';
  3600.       already_signed = 1;
  3601.     }
  3602.  
  3603.   ret = netname_check_in (name_server_port,    /* Name server port */
  3604.               name,            /* Name of service */
  3605.               our_message_port,    /* Signature */
  3606.               port);         /* Creates a new send right */
  3607.   CHK("Failed to check in the port", ret);
  3608.   
  3609.   len = 0;
  3610.   while(len < MAX_NAME_LEN && *(name+len))
  3611.     {
  3612.       registered_name[len] = *(name+len);
  3613.       len++;
  3614.     }
  3615.   registered_name[len] = '\000';
  3616.   already_signed = 2;
  3617. }  
  3618.  
  3619. struct cmd_list_element *cmd_thread_list;
  3620. struct cmd_list_element *cmd_task_list;
  3621.  
  3622. /*ARGSUSED*/
  3623. static void
  3624. thread_command (arg, from_tty)
  3625.      char *arg;
  3626.      int from_tty;
  3627. {
  3628.   printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
  3629.   help_list (cmd_thread_list, "thread ", -1, gdb_stdout);
  3630. }
  3631.  
  3632. /*ARGSUSED*/
  3633. static void
  3634. task_command (arg, from_tty)
  3635.      char *arg;
  3636.      int from_tty;
  3637. {
  3638.   printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
  3639.   help_list (cmd_task_list, "task ", -1, gdb_stdout);
  3640. }
  3641.  
  3642. add_mach_specific_commands ()
  3643. {
  3644.   extern void condition_thread ();
  3645.  
  3646.   /* Thread handling commands */
  3647.  
  3648.   /* FIXME: Move our thread support into the generic thread.c stuff so we
  3649.      can share that code.  */
  3650.   add_prefix_cmd ("mthread", class_stack, thread_command,
  3651.       "Generic command for handling Mach threads in the debugged task.",
  3652.       &cmd_thread_list, "thread ", 0, &cmdlist);
  3653.  
  3654.   add_com_alias ("th", "mthread", class_stack, 1);
  3655.  
  3656.   add_cmd ("select", class_stack, thread_select_command, 
  3657.        "Select and print MID of the selected thread",
  3658.        &cmd_thread_list);
  3659.   add_cmd ("list",   class_stack, thread_list_command,
  3660.        "List info of task's threads. Selected thread is marked with '*'",
  3661.        &cmd_thread_list);
  3662.   add_cmd ("suspend", class_run, thread_suspend_command,
  3663.        "Suspend one or all of the threads in the selected task.",
  3664.        &cmd_thread_list);
  3665.   add_cmd ("resume", class_run, thread_resume_command,
  3666.        "Resume one or all of the threads in the selected task.",
  3667.        &cmd_thread_list);
  3668.   add_cmd ("kill", class_run, thread_kill_command,
  3669.        "Kill the specified thread MID from inferior task.",
  3670.        &cmd_thread_list);
  3671.   add_cmd ("break", class_breakpoint, condition_thread,
  3672.        "Breakpoint N will only be effective for thread MID or @SLOT\n\
  3673.         If MID/@SLOT is omitted allow all threads to break at breakpoint",
  3674.        &cmd_thread_list);
  3675.   /* Thread command shorthands (for backward compatibility) */
  3676.   add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist);
  3677.   add_alias_cmd ("tl", "mthread list",   0, 0, &cmdlist);
  3678.  
  3679.   /* task handling commands */
  3680.  
  3681.   add_prefix_cmd ("task", class_stack, task_command,
  3682.       "Generic command for handling debugged task.",
  3683.       &cmd_task_list, "task ", 0, &cmdlist);
  3684.  
  3685.   add_com_alias ("ta", "task", class_stack, 1);
  3686.  
  3687.   add_cmd ("suspend", class_run, task_suspend_command,
  3688.        "Suspend the inferior task.",
  3689.        &cmd_task_list);
  3690.   add_cmd ("resume", class_run, task_resume_command,
  3691.        "Resume the inferior task.",
  3692.        &cmd_task_list);
  3693.   add_cmd ("info", no_class, task_info_command,
  3694.        "Print information about the specified task.",
  3695.        &cmd_task_list);
  3696.  
  3697.   /* Print my message port name */
  3698.  
  3699.   add_info ("message-port", message_port_info,
  3700.         "Returns the name of gdb's message port in the netnameserver");
  3701.  
  3702.   /* Exception commands */
  3703.  
  3704.   add_info ("exceptions", exception_info,
  3705.         "What debugger does when program gets various exceptions.\n\
  3706. Specify an exception number as argument to print info on that\n\
  3707. exception only.");
  3708.  
  3709.   add_com ("exception", class_run, exception_command,
  3710.        "Specify how to handle an exception.\n\
  3711. Args are exception number followed by \"forward\" or \"keep\".\n\
  3712. `Forward' means forward the exception to the program's normal exception\n\
  3713. handler.\n\
  3714. `Keep' means reenter debugger if this exception happens, and GDB maps\n\
  3715. the exception to some signal (see info exception)\n\
  3716. Normally \"keep\" is used to return to GDB on exception.");
  3717. }
  3718.  
  3719. kern_return_t
  3720. do_mach_notify_dead_name (notify, name)
  3721.      mach_port_t notify;
  3722.      mach_port_t name;
  3723. {
  3724.   kern_return_t kr = KERN_SUCCESS;
  3725.  
  3726.   /* Find the thing that notified */
  3727.   port_chain_t element = port_chain_member (notify_chain, name);
  3728.  
  3729.   /* Take name of from unreceived dead name notification list */
  3730.   notify_chain = port_chain_delete (notify_chain, name);
  3731.  
  3732.   if (! element)
  3733.     error ("Received a dead name notify from unchained port (0x%x)", name);
  3734.   
  3735.   switch (element->type) {
  3736.  
  3737.   case MACH_TYPE_THREAD:
  3738.     target_terminal_ours_for_output ();
  3739.     if (name == current_thread)
  3740.       {
  3741.     printf_filtered ("\nCurrent thread %d died", element->mid);
  3742.     current_thread = MACH_PORT_NULL;
  3743.       }
  3744.     else
  3745.       printf_filtered ("\nThread %d died", element->mid);
  3746.  
  3747.     break;
  3748.  
  3749.   case MACH_TYPE_TASK:
  3750.     target_terminal_ours_for_output ();
  3751.     if (name != inferior_task)
  3752.       printf_filtered ("Task %d died, but it was not the selected task",
  3753.            element->mid);
  3754.     else           
  3755.       {
  3756.     printf_filtered ("Current task %d died", element->mid);
  3757.     
  3758.     mach_port_destroy (mach_task_self(), name);
  3759.     inferior_task = MACH_PORT_NULL;
  3760.     
  3761.     if (notify_chain)
  3762.       warning ("There were still unreceived dead_name_notifications???");
  3763.     
  3764.     /* Destroy the old notifications */
  3765.     setup_notify_port (0);
  3766.  
  3767.       }
  3768.     break;
  3769.  
  3770.   default:
  3771.     error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
  3772.        name, element->type, element->mid);
  3773.     break;
  3774.   }
  3775.  
  3776.   return KERN_SUCCESS;
  3777. }
  3778.  
  3779. kern_return_t
  3780. do_mach_notify_msg_accepted (notify, name)
  3781.      mach_port_t notify;
  3782.      mach_port_t name;
  3783. {
  3784.   warning ("do_mach_notify_msg_accepted : notify %x, name %x",
  3785.        notify, name);
  3786.   return KERN_SUCCESS;
  3787. }
  3788.  
  3789. kern_return_t
  3790. do_mach_notify_no_senders (notify, mscount)
  3791.      mach_port_t notify;
  3792.      mach_port_mscount_t mscount;
  3793. {
  3794.   warning ("do_mach_notify_no_senders : notify %x, mscount %x",
  3795.        notify, mscount);
  3796.   return KERN_SUCCESS;
  3797. }
  3798.  
  3799. kern_return_t
  3800. do_mach_notify_port_deleted (notify, name)
  3801.      mach_port_t notify;
  3802.      mach_port_t name;
  3803. {
  3804.   warning ("do_mach_notify_port_deleted : notify %x, name %x",
  3805.        notify, name);
  3806.   return KERN_SUCCESS;
  3807. }
  3808.  
  3809. kern_return_t
  3810. do_mach_notify_port_destroyed (notify, rights)
  3811.      mach_port_t notify;
  3812.      mach_port_t rights;
  3813. {
  3814.   warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
  3815.        notify, rights);
  3816.   return KERN_SUCCESS;
  3817. }
  3818.  
  3819. kern_return_t
  3820. do_mach_notify_send_once (notify)
  3821.      mach_port_t notify;
  3822. {
  3823. #ifdef DUMP_SYSCALL
  3824.   /* MANY of these are generated. */
  3825.   warning ("do_mach_notify_send_once : notify %x",
  3826.        notify);
  3827. #endif
  3828.   return KERN_SUCCESS;
  3829. }
  3830.  
  3831. /* Kills the inferior. It's gone when you call this */
  3832. static void
  3833. kill_inferior_fast ()
  3834. {
  3835.   WAITTYPE w;
  3836.  
  3837.   if (inferior_pid == 0 || inferior_pid == 1)
  3838.     return;
  3839.  
  3840.   /* kill() it, since the Unix server does not otherwise notice when
  3841.    * killed with task_terminate().
  3842.    */
  3843.   if (inferior_pid > 0)
  3844.     kill (inferior_pid, SIGKILL);
  3845.  
  3846.   /* It's propably terminate already */
  3847.   (void) task_terminate (inferior_task);
  3848.  
  3849.   inferior_task  = MACH_PORT_NULL;
  3850.   current_thread = MACH_PORT_NULL;
  3851.  
  3852.   wait3 (&w, WNOHANG, 0);
  3853.  
  3854.   setup_notify_port (0);
  3855. }
  3856.  
  3857. static void
  3858. m3_kill_inferior ()
  3859. {
  3860.   kill_inferior_fast ();
  3861.   target_mourn_inferior ();
  3862. }
  3863.  
  3864. /* Clean up after the inferior dies.  */
  3865.  
  3866. static void
  3867. m3_mourn_inferior ()
  3868. {
  3869.   unpush_target (&m3_ops);
  3870.   generic_mourn_inferior ();
  3871. }
  3872.  
  3873.  
  3874. /* Fork an inferior process, and start debugging it.  */
  3875.  
  3876. static void
  3877. m3_create_inferior (exec_file, allargs, env)
  3878.      char *exec_file;
  3879.      char *allargs;
  3880.      char **env;
  3881. {
  3882.   fork_inferior (exec_file, allargs, env, m3_trace_m3, m3_trace_him);
  3883.   /* We are at the first instruction we care about.  */
  3884.   /* Pedal to the metal... */
  3885.   proceed ((CORE_ADDR) -1, 0, 0);
  3886. }
  3887.  
  3888. /* Mark our target-struct as eligible for stray "run" and "attach"
  3889.    commands.  */
  3890. static int
  3891. m3_can_run ()
  3892. {
  3893.   return 1;
  3894. }
  3895.  
  3896. /* Mach 3.0 does not need ptrace for anything
  3897.  * Make sure nobody uses it on mach.
  3898.  */
  3899. ptrace (a,b,c,d)
  3900. int a,b,c,d;
  3901. {
  3902.   error ("Lose, Lose! Somebody called ptrace\n");
  3903. }
  3904.  
  3905. /* Resume execution of the inferior process.
  3906.    If STEP is nonzero, single-step it.
  3907.    If SIGNAL is nonzero, give it that signal.  */
  3908.  
  3909. void
  3910. m3_resume (pid, step, signal)
  3911.      int pid;
  3912.      int step;
  3913.      enum target_signal signal;
  3914. {
  3915.   kern_return_t    ret;
  3916.  
  3917.   if (step)
  3918.     {
  3919.       thread_basic_info_data_t th_info;
  3920.       unsigned int           infoCnt = THREAD_BASIC_INFO_COUNT;
  3921.       
  3922.       /* There is no point in single stepping when current_thread
  3923.        * is dead.
  3924.        */
  3925.       if (! MACH_PORT_VALID (current_thread))
  3926.     error ("No thread selected; can not single step");
  3927.       
  3928.       /* If current_thread is suspended, tracing it would never return.
  3929.        */
  3930.       ret = thread_info (current_thread,
  3931.              THREAD_BASIC_INFO,
  3932.              (thread_info_t) &th_info,
  3933.              &infoCnt);
  3934.       CHK ("child_resume: can't get thread info", ret);
  3935.       
  3936.       if (th_info.suspend_count)
  3937.     error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
  3938.     }
  3939.  
  3940.   vm_read_cache_valid = FALSE;
  3941.  
  3942.   if (signal && inferior_pid > 0) /* Do not signal, if attached by MID */
  3943.     kill (inferior_pid, target_signal_to_host (signal));
  3944.  
  3945.   if (step)
  3946.     {
  3947.       suspend_all_threads (0);
  3948.  
  3949.       setup_single_step (current_thread, TRUE);
  3950.       
  3951.       ret = thread_resume (current_thread);
  3952.       CHK ("thread_resume", ret);
  3953.     }
  3954.   
  3955.   ret = task_resume (inferior_task);
  3956.   if (ret == KERN_FAILURE)
  3957.     warning ("Task was not suspended");
  3958.   else
  3959.     CHK ("Resuming task", ret);
  3960.   
  3961.   /* HACK HACK This is needed by the multiserver system HACK HACK */
  3962.   while ((ret = task_resume(inferior_task)) == KERN_SUCCESS)
  3963.     /* make sure it really runs */;
  3964.   /* HACK HACK This is needed by the multiserver system HACK HACK */
  3965. }
  3966.  
  3967. #ifdef ATTACH_DETACH
  3968.  
  3969. /* Start debugging the process with the given task */
  3970. void
  3971. task_attach (tid)
  3972.   task_t tid;
  3973. {
  3974.   kern_return_t ret;
  3975.   inferior_task = tid;
  3976.  
  3977.   ret = task_suspend (inferior_task);
  3978.   CHK("task_attach: task_suspend", ret);
  3979.  
  3980.   must_suspend_thread = 0;
  3981.  
  3982.   setup_notify_port (1);
  3983.  
  3984.   request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
  3985.  
  3986.   setup_exception_port ();
  3987.   
  3988.   emulator_present = have_emulator_p (inferior_task);
  3989.  
  3990.   attach_flag = 1;
  3991. }
  3992.  
  3993. /* Well, we can call error also here and leave the
  3994.  * target stack inconsistent. Sigh.
  3995.  * Fix this sometime (the only way to fail here is that
  3996.  * the task has no threads at all, which is rare, but
  3997.  * possible; or if the target task has died, which is also
  3998.  * possible, but unlikely, since it has been suspended.
  3999.  * (Someone must have killed it))
  4000.  */
  4001. void
  4002. attach_to_thread ()
  4003. {
  4004.   if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
  4005.     error ("Could not select any threads to attach to");
  4006. }
  4007.  
  4008. mid_attach (mid)
  4009.     int    mid;
  4010. {
  4011.     kern_return_t ret;
  4012.  
  4013.     ret = machid_mach_port (mid_server, mid_auth, mid, &inferior_task);
  4014.     CHK("mid_attach: machid_mach_port", ret);
  4015.  
  4016.     task_attach (inferior_task);
  4017.  
  4018.     return mid;
  4019. }
  4020.  
  4021. /* 
  4022.  * Start debugging the process whose unix process-id is PID.
  4023.  * A negative "pid" value is legal and signifies a mach_id not a unix pid.
  4024.  *
  4025.  * Prevent (possible unwanted) dangerous operations by enabled users
  4026.  * like "atta 0" or "atta foo" (equal to the previous :-) and
  4027.  * "atta pidself". Anyway, the latter is allowed by specifying a MID.
  4028.  */
  4029. static int
  4030. m3_do_attach (pid)
  4031.      int pid;
  4032. {
  4033.   kern_return_t ret;
  4034.  
  4035.   if (pid == 0)
  4036.     error("MID=0, Debugging the master unix server does not compute");
  4037.  
  4038.   /* Foo. This assumes gdb has a unix pid */
  4039.   if (pid == getpid())
  4040.     error ("I will debug myself only by mid. (Gdb would suspend itself!)");
  4041.  
  4042.   if (pid < 0)
  4043.     {
  4044.       mid_attach (-(pid));
  4045.  
  4046.       /* inferior_pid will be NEGATIVE! */
  4047.       inferior_pid = pid;
  4048.  
  4049.       return inferior_pid;
  4050.     }
  4051.  
  4052.   inferior_task = task_by_pid (pid);
  4053.   if (! MACH_PORT_VALID (inferior_task))
  4054.     error("Cannot map Unix pid %d to Mach task port", pid);
  4055.  
  4056.   task_attach (inferior_task);
  4057.  
  4058.   inferior_pid = pid;
  4059.  
  4060.   return inferior_pid;
  4061. }
  4062.  
  4063. /* Attach to process PID, then initialize for debugging it
  4064.    and wait for the trace-trap that results from attaching.  */
  4065.  
  4066. static void
  4067. m3_attach (args, from_tty)
  4068.      char *args;
  4069.      int from_tty;
  4070. {
  4071.   char *exec_file;
  4072.   int pid;
  4073.  
  4074.   if (!args)
  4075.     error_no_arg ("process-id to attach");
  4076.  
  4077.   pid = atoi (args);
  4078.  
  4079.   if (pid == getpid())        /* Trying to masturbate? */
  4080.     error ("I refuse to debug myself!");
  4081.  
  4082.   if (from_tty)
  4083.     {
  4084.       exec_file = (char *) get_exec_file (0);
  4085.  
  4086.       if (exec_file)
  4087.     printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
  4088.       else
  4089.     printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
  4090.  
  4091.       gdb_flush (gdb_stdout);
  4092.     }
  4093.  
  4094.   m3_do_attach (pid);
  4095.   inferior_pid = pid;
  4096.   push_target (&procfs_ops);
  4097. }
  4098.  
  4099. void
  4100. deallocate_inferior_ports ()
  4101. {
  4102.   kern_return_t  ret;
  4103.   thread_array_t thread_list;
  4104.   int         thread_count, index;
  4105.  
  4106.   if (!MACH_PORT_VALID (inferior_task))
  4107.     return;
  4108.  
  4109.   ret = task_threads (inferior_task, &thread_list, &thread_count);
  4110.   if (ret != KERN_SUCCESS)
  4111.     {
  4112.       warning ("deallocate_inferior_ports: task_threads",
  4113.            mach_error_string(ret));
  4114.       return;
  4115.     }
  4116.  
  4117.   /* Get rid of send rights to task threads */
  4118.   for (index = 0; index < thread_count; index++)
  4119.     {
  4120.       int rights;
  4121.       ret = mach_port_get_refs (mach_task_self (),
  4122.                 thread_list[index],
  4123.                 MACH_PORT_RIGHT_SEND,
  4124.                 &rights);
  4125.       CHK("deallocate_inferior_ports: get refs", ret);
  4126.  
  4127.       if (rights > 0)
  4128.     {
  4129.       ret = mach_port_mod_refs (mach_task_self (),
  4130.                     thread_list[index],
  4131.                     MACH_PORT_RIGHT_SEND,
  4132.                     -rights);
  4133.       CHK("deallocate_inferior_ports: mod refs", ret);
  4134.     }
  4135.     }
  4136.  
  4137.   ret = mach_port_mod_refs (mach_task_self (),
  4138.                 inferior_exception_port,
  4139.                 MACH_PORT_RIGHT_RECEIVE,
  4140.                 -1);
  4141.   CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret);
  4142.  
  4143.   ret = mach_port_deallocate (mach_task_self (),
  4144.                   inferior_task);
  4145.   CHK ("deallocate_task_port: deallocating inferior_task", ret);
  4146.  
  4147.   current_thread = MACH_PORT_NULL;
  4148.   inferior_task  = MACH_PORT_NULL;
  4149. }
  4150.  
  4151. /* Stop debugging the process whose number is PID
  4152.    and continue it with signal number SIGNAL.
  4153.    SIGNAL = 0 means just continue it.  */
  4154.  
  4155. static void
  4156. m3_do_detach (signal)
  4157.      int signal;
  4158. {
  4159.   kern_return_t ret;
  4160.  
  4161.   MACH_ERROR_NO_INFERIOR;
  4162.  
  4163.   if (current_thread != MACH_PORT_NULL)
  4164.     {
  4165.       /* Store the gdb's view of the thread we are deselecting
  4166.        * before we detach.
  4167.        * @@ I am really not sure if this is ever needeed.
  4168.        */
  4169.       target_prepare_to_store ();
  4170.       target_store_registers (-1);
  4171.     }
  4172.  
  4173.   ret = task_set_special_port (inferior_task,
  4174.                    TASK_EXCEPTION_PORT, 
  4175.                    inferior_old_exception_port);
  4176.   CHK ("task_set_special_port", ret);
  4177.  
  4178.   /* Discard all requested notifications */
  4179.   setup_notify_port (0);
  4180.  
  4181.   if (remove_breakpoints ())
  4182.     warning ("Could not remove breakpoints when detaching");
  4183.   
  4184.   if (signal && inferior_pid > 0)
  4185.     kill (inferior_pid, signal);
  4186.   
  4187.   /* the task might be dead by now */
  4188.   (void) task_resume (inferior_task);
  4189.   
  4190.   deallocate_inferior_ports ();
  4191.   
  4192.   attach_flag = 0;
  4193. }
  4194.  
  4195. /* Take a program previously attached to and detaches it.
  4196.    The program resumes execution and will no longer stop
  4197.    on signals, etc.  We'd better not have left any breakpoints
  4198.    in the program or it'll die when it hits one.  For this
  4199.    to work, it may be necessary for the process to have been
  4200.    previously attached.  It *might* work if the program was
  4201.    started via fork.  */
  4202.  
  4203. static void
  4204. m3_detach (args, from_tty)
  4205.      char *args;
  4206.      int from_tty;
  4207. {
  4208.   int siggnal = 0;
  4209.  
  4210.   if (from_tty)
  4211.     {
  4212.       char *exec_file = get_exec_file (0);
  4213.       if (exec_file == 0)
  4214.     exec_file = "";
  4215.       printf_unfiltered ("Detaching from program: %s %s\n",
  4216.           exec_file, target_pid_to_str (inferior_pid));
  4217.       gdb_flush (gdb_stdout);
  4218.     }
  4219.   if (args)
  4220.     siggnal = atoi (args);
  4221.   
  4222.   m3_do_detach (siggnal);
  4223.   inferior_pid = 0;
  4224.   unpush_target (&m3_ops);        /* Pop out of handling an inferior */
  4225. }
  4226. #endif /* ATTACH_DETACH */
  4227.  
  4228. #ifdef DUMP_SYSCALL
  4229. #ifdef __STDC__
  4230. #define STR(x) #x
  4231. #else
  4232. #define STR(x) "x"
  4233. #endif
  4234.  
  4235. char    *bsd1_names[] = {
  4236.   "execve",
  4237.   "fork",
  4238.   "take_signal",
  4239.   "sigreturn",
  4240.   "getrusage",
  4241.   "chdir",
  4242.   "chroot",
  4243.   "open",
  4244.   "creat",
  4245.   "mknod",
  4246.   "link",
  4247.   "symlink",
  4248.   "unlink",
  4249.   "access",
  4250.   "stat",
  4251.   "readlink",
  4252.   "chmod",
  4253.   "chown",
  4254.   "utimes",
  4255.   "truncate",
  4256.   "rename",
  4257.   "mkdir",
  4258.   "rmdir",
  4259.   "xutimes",
  4260.   "mount",
  4261.   "umount",
  4262.   "acct",
  4263.   "setquota",
  4264.   "write_short",
  4265.   "write_long",
  4266.   "send_short",
  4267.   "send_long",
  4268.   "sendto_short",
  4269.   "sendto_long",
  4270.   "select",
  4271.   "task_by_pid",
  4272.   "recvfrom_short",
  4273.   "recvfrom_long",
  4274.   "setgroups",
  4275.   "setrlimit",
  4276.   "sigvec",
  4277.   "sigstack",
  4278.   "settimeofday",
  4279.   "adjtime",
  4280.   "setitimer",
  4281.   "sethostname",
  4282.   "bind",
  4283.   "accept",
  4284.   "connect",
  4285.   "setsockopt",
  4286.   "getsockopt",
  4287.   "getsockname",
  4288.   "getpeername",
  4289.   "init_process",
  4290.   "table_set",
  4291.   "table_get",
  4292.   "pioctl",
  4293.   "emulator_error",
  4294.   "readwrite",
  4295.   "share_wakeup",
  4296.   0,
  4297.   "maprw_request_it",
  4298.   "maprw_release_it",
  4299.   "maprw_remap",
  4300.   "pid_by_task",
  4301. };
  4302.  
  4303. int    bsd1_nnames = sizeof(bsd1_names)/sizeof(bsd1_names[0]);
  4304.  
  4305. char*
  4306. name_str(name,buf)
  4307.  
  4308. int    name;
  4309. char    *buf;
  4310.  
  4311. {
  4312.   switch (name) {
  4313.   case MACH_MSG_TYPE_BOOLEAN:
  4314.     return "boolean";
  4315.   case MACH_MSG_TYPE_INTEGER_16:
  4316.     return "short";
  4317.   case MACH_MSG_TYPE_INTEGER_32:
  4318.     return "long";
  4319.   case MACH_MSG_TYPE_CHAR:
  4320.     return "char";
  4321.   case MACH_MSG_TYPE_BYTE:
  4322.     return "byte";
  4323.   case MACH_MSG_TYPE_REAL:
  4324.     return "real";
  4325.   case MACH_MSG_TYPE_STRING:
  4326.     return "string";
  4327.   default:
  4328.     sprintf(buf,"%d",name);
  4329.     return buf;
  4330.   }
  4331. }
  4332.  
  4333. char *
  4334. id_str(id,buf)
  4335.  
  4336. int    id;
  4337. char    *buf;
  4338.  
  4339. {
  4340.   char    *p;
  4341.   if (id >= 101000 && id < 101000+bsd1_nnames) {
  4342.     if (p = bsd1_names[id-101000])
  4343.       return p;
  4344.   }
  4345.   if (id == 102000)
  4346.     return "psignal_retry";
  4347.   if (id == 100000)
  4348.     return "syscall";
  4349.   sprintf(buf,"%d",id);
  4350.   return buf;
  4351. }
  4352.  
  4353. print_msg(mp)
  4354. mach_msg_header_t    *mp;
  4355. {
  4356.   char    *fmt_x = "%20s : 0x%08x\n";
  4357.   char    *fmt_d = "%20s : %10d\n";
  4358.   char    *fmt_s = "%20s : %s\n";
  4359.   char    buf[100];
  4360.  
  4361.   puts_filtered ("\n");
  4362. #define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
  4363.   pr(fmt_x,(*mp),msgh_bits);
  4364.   pr(fmt_d,(*mp),msgh_size);
  4365.   pr(fmt_x,(*mp),msgh_remote_port);
  4366.   pr(fmt_x,(*mp),msgh_local_port);
  4367.   pr(fmt_d,(*mp),msgh_kind);
  4368.   printf_filtered(fmt_s,STR(msgh_id),id_str(mp->msgh_id,buf));
  4369.   
  4370.   if (debug_level > 1)
  4371.   {
  4372.     char    *p,*ep,*dp;
  4373.     int        plen;
  4374.     p = (char*)mp;
  4375.     ep = p+mp->msgh_size;
  4376.     p += sizeof(*mp);
  4377.     for(; p < ep; p += plen) {
  4378.       mach_msg_type_t    *tp;
  4379.       mach_msg_type_long_t    *tlp;
  4380.       int    name,size,number;
  4381.       tp = (mach_msg_type_t*)p;
  4382.       if (tp->msgt_longform) {
  4383.     tlp = (mach_msg_type_long_t*)tp;
  4384.     name = tlp->msgtl_name;
  4385.     size = tlp->msgtl_size;
  4386.     number = tlp->msgtl_number;
  4387.     plen = sizeof(*tlp);
  4388.       } else {
  4389.     name = tp->msgt_name;
  4390.     size = tp->msgt_size;
  4391.     number = tp->msgt_number;
  4392.     plen = sizeof(*tp);
  4393.       }
  4394.       printf_filtered("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
  4395.               name_str(name,buf),size,number,tp->msgt_inline,
  4396.               tp->msgt_longform, tp->msgt_deallocate);
  4397.       dp = p+plen;
  4398.       if (tp->msgt_inline) {
  4399.     int    l;
  4400.     l = size*number/8;
  4401.     l = (l+sizeof(long)-1)&~((sizeof(long))-1);
  4402.     plen += l;
  4403.     print_data(dp,size,number);
  4404.       } else {
  4405.     plen += sizeof(int*);
  4406.       }
  4407.       printf_filtered("plen=%d\n",plen);
  4408.     }
  4409.   }
  4410. }
  4411.  
  4412. print_data(p,size,number)
  4413.  
  4414. char    *p;
  4415.  
  4416. {
  4417.   int    *ip;
  4418.   short    *sp;
  4419.   int    i;
  4420.  
  4421.   switch (size) {
  4422.   case 8:
  4423.     for(i = 0; i < number; i++) {
  4424.       printf_filtered(" %02x",p[i]);
  4425.     }
  4426.     break;
  4427.   case 16:
  4428.     sp = (short*)p;
  4429.     for(i = 0; i < number; i++) {
  4430.       printf_filtered(" %04x",sp[i]);
  4431.     }
  4432.     break;
  4433.   case 32:
  4434.     ip = (int*)p;
  4435.     for(i = 0; i < number; i++) {
  4436.       printf_filtered(" %08x",ip[i]);
  4437.     }
  4438.     break;
  4439.   }
  4440.   puts_filtered("\n");
  4441. }
  4442. #endif  DUMP_SYSCALL
  4443.  
  4444. struct target_ops m3_ops = {
  4445.   "mach",            /* to_shortname */
  4446.   "Mach child process",    /* to_longname */
  4447.   "Mach child process (started by the \"run\" command).",    /* to_doc */
  4448.   ??_open,            /* to_open */
  4449.   0,                /* to_close */
  4450.   m3_attach,            /* to_attach */
  4451.   m3_detach,         /* to_detach */
  4452.   m3_resume,            /* to_resume */
  4453.   mach_really_wait,            /* to_wait */
  4454.   fetch_inferior_registers,    /* to_fetch_registers */
  4455.   store_inferior_registers,    /* to_store_registers */
  4456.   child_prepare_to_store,    /* to_prepare_to_store */
  4457.   m3_xfer_memory,        /* to_xfer_memory */
  4458.  
  4459.   /* FIXME: Should print MID and all that crap.  */
  4460.   child_files_info,        /* to_files_info */
  4461.  
  4462.   memory_insert_breakpoint,    /* to_insert_breakpoint */
  4463.   memory_remove_breakpoint,    /* to_remove_breakpoint */
  4464.   terminal_init_inferior,    /* to_terminal_init */
  4465.   terminal_inferior,         /* to_terminal_inferior */
  4466.   terminal_ours_for_output,    /* to_terminal_ours_for_output */
  4467.   terminal_ours,        /* to_terminal_ours */
  4468.   child_terminal_info,        /* to_terminal_info */
  4469.   m3_kill_inferior,        /* to_kill */
  4470.   0,                /* to_load */
  4471.   0,                /* to_lookup_symbol */
  4472.  
  4473.   m3_create_inferior,    /* to_create_inferior */
  4474.   m3_mourn_inferior,    /* to_mourn_inferior */
  4475.   m3_can_run,        /* to_can_run */
  4476.   0,                /* to_notice_signals */
  4477.   process_stratum,        /* to_stratum */
  4478.   0,                /* to_next */
  4479.   1,                /* to_has_all_memory */
  4480.   1,                /* to_has_memory */
  4481.   1,                /* to_has_stack */
  4482.   1,                /* to_has_registers */
  4483.   1,                /* to_has_execution */
  4484.   0,                /* sections */
  4485.   0,                /* sections_end */
  4486.   OPS_MAGIC            /* to_magic */
  4487. };
  4488.  
  4489. void
  4490. _initialize_m3_nat ()
  4491. {
  4492.   kern_return_t ret;
  4493.  
  4494.   add_target (&m3_ops);
  4495.  
  4496.   ret = mach_port_allocate(mach_task_self(), 
  4497.                MACH_PORT_RIGHT_PORT_SET,
  4498.                &inferior_wait_port_set);
  4499.   if (ret != KERN_SUCCESS)
  4500.     fatal("initial port set %s",mach_error_string(ret));
  4501.  
  4502.   /* mach_really_wait now waits for this */
  4503.   currently_waiting_for = inferior_wait_port_set;
  4504.  
  4505.   ret = netname_look_up(name_server_port, hostname, "MachID", &mid_server);
  4506.   if (ret != KERN_SUCCESS)
  4507.     {
  4508.       mid_server = MACH_PORT_NULL;
  4509.       
  4510.       warning ("initialize machid: netname_lookup_up(MachID) : %s",
  4511.            mach_error_string(ret));
  4512.       warning ("Some (most?) features disabled...");
  4513.     }
  4514.   
  4515.   mid_auth = mach_privileged_host_port();
  4516.   if (mid_auth == MACH_PORT_NULL)
  4517.     mid_auth = mach_task_self();
  4518.   
  4519.   obstack_init (port_chain_obstack);
  4520.  
  4521.   ret = mach_port_allocate (mach_task_self (), 
  4522.                 MACH_PORT_RIGHT_RECEIVE,
  4523.                 &thread_exception_port);
  4524.   CHK ("Creating thread_exception_port for single stepping", ret);
  4525.   
  4526.   ret = mach_port_insert_right (mach_task_self (),
  4527.                 thread_exception_port,
  4528.                 thread_exception_port,
  4529.                 MACH_MSG_TYPE_MAKE_SEND);
  4530.   CHK ("Inserting send right to thread_exception_port", ret);
  4531.  
  4532.   /* Allocate message port */
  4533.   ret = mach_port_allocate (mach_task_self (),
  4534.                 MACH_PORT_RIGHT_RECEIVE,
  4535.                 &our_message_port);
  4536.   if (ret != KERN_SUCCESS)
  4537.     warning ("Creating message port %s", mach_error_string (ret));
  4538.   else
  4539.     {
  4540.       char buf[ MAX_NAME_LEN ];
  4541.       ret = mach_port_move_member(mach_task_self (),
  4542.                   our_message_port,
  4543.                   inferior_wait_port_set);
  4544.       if (ret != KERN_SUCCESS)
  4545.     warning ("message move member %s", mach_error_string (ret));
  4546.  
  4547.  
  4548.       /* @@@@ No way to change message port name currently */
  4549.       /* Foo. This assumes gdb has a unix pid */
  4550.       sprintf (buf, "gdb-%d", getpid ());
  4551.       gdb_register_port (buf, our_message_port);
  4552.     }
  4553.   
  4554.   /* Heap for thread commands */
  4555.   obstack_init (cproc_obstack);
  4556.  
  4557.   add_mach_specific_commands ();
  4558. }
  4559.